c++11 - 按值传递函数中的附加移动构造函数

标签 c++11

我有一个简单的结构,定义了所有构造函数。 它有一个 int 变量,每个构造函数和赋值运算符打印 *this 的地址、int 的当前值和 int 的新值。 移动和复制赋值运算符和构造函数也会打印传递值的地址。

#include <iostream>

struct X
{
    int val;
    void out(const std::string& s, int nv, const X* from = nullptr)
    {
        std::cout<<this<<"->"<<s<<": "<<val<<" ("<<nv<<")";
        if (from)
            std::cout<<", from: ["<<from<<"]";
        std::cout<<"\n";
    }

    X(){out("simple ctor X()",0); val = 0;}
    X(int v){out("int ctor X(int)", v);val = v; }
    X(const X& x){out("copy ctor X(X&)", x.val, &x);val = x.val; };
    X&operator = (const X& x){out("copy X::operator=()", x.val, &x); val = x.val; return *this;}
    ~X(){out("dtor ~X", 0);}
    X&operator = (X&& x){out("move X::operator(&&)", x.val, &x); val = x.val; return *this;}
    X(X&& x){out("move ctor X(&&x)", x.val, &x);val = x.val;}
};

X copy(X a){return a;}

int main(int argc, const char * argv[]) {
    X loc{4};
    X loc2;
    std::cout<<"before copy\n";
    loc2 = copy(loc);
    std::cout<<"copy finish\n";
}

输出:

0xffdf7278->int ctor X(int): 134523184 (4)
0xffdf727c->simple ctor X(): 134514433 (0)
before copy
0xffdf7280->copy ctor X(X&): 1433459488 (4), from: [0xffdf7278]
0xffdf7284->move ctor X(&&x): 1433437824 (4), from: [0xffdf7280]
0xffdf727c->move X::operator(&&): 0 (4), from: [0xffdf7284]
0xffdf7284->dtor ~X: 4 (0)
0xffdf7280->dtor ~X: 4 (0)
copy finish
0xffdf727c->dtor ~X: 4 (0)
0xffdf7278->dtor ~X: 4 (0)

(在本例中)创建地址为 0xffdf7284 的附加对象的目的是什么?

最佳答案

如果你看copy elision rules from cppreference.com ,您可以注意到,在两种情况下,编译器需要省略类对象的复制和移动构造函数即使复制/移动构造函数和析构函数具有可观察到的副作用(您的做,由于打印输出)。第一个显然与本案无关。第二个是

In a function call, if the operand of a return statement is a prvalue and the return type of the function is the same as the type of that prvalue.

给出的例子是:

T f() { return T{}; }
T x = f();  

这似乎更相关,但是请注意,在您的情况下,return 语句的操作数不是 prvalue 。因此在这种情况下,不适用强制省略。

调用loc2 = copy(loc);时的步骤如下:

  • a 是从 loc 复制构造的。
  • 函数的返回值是从 a 移动构造的。
  • loc2 是根据返回值进行移动分配的。

从逻辑上讲,人们可以查看代码并推断出需要完成的操作更少(特别是,当查看copy时,很明显,从逻辑上讲,来自loc的赋值loc2 就足够了),但编译器不知道代码的目的不是生成副作用(打印输出),并且它没有违反任何规则在这里。

关于c++11 - 按值传递函数中的附加移动构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39633265/

相关文章:

c++ - 如何读取控制台输入并将其存储到 vector 字符串中

c++ - 可变参数模板问题

c++ - 试图从 std::function 获取普通函数指针

c++ - 抛出异常后捕获 block 调试语句不执行?

c++ - 有人能告诉我为什么这不是常量表达式吗?

c++ - 返回 unique_ptr 还是只是移动对象?

c++ - 当 auto 遇到多态和虚函数时,正确的行为是什么?

c++ - 用计数器扩展参数包

c++ - 在迷宫 C++ 中查找路径是否存在

c++ - 为什么即使调用了析构函数,C++11 中的分离线程也能执行