2016-09-22 64 views
2

我有一个简单的结构,它具有所有定义的构造函数。 它有一个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的目的是什么?

回答

2

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

在函数调用中,如果return语句的操作数是prvalue,并且函数的返回类型与该prvalue的类型相同。

随着给出的例子:

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

这似乎更具相关性,但是,请注意,在你的情况下,return声明的操作数是不是prvalue。所以在这种情况下,没有强制性的elision适用。

的一组步骤,主叫loc2 = copy(loc);时,如下:

  • a是拷贝构造从loc
  • 函数的返回值是从a移动构建的。
  • loc2是从返回值移动分配的。

从逻辑上讲,一个人可以看代码,并推断出较少操作需要做的(尤其是看着copy时,很明显的是,在逻辑上,从locloc2的分配就足够了),但编译器不知道您的代码的目的不是产生副作用(打印输出),并且这里没有违反任何规则。

+0

那么,它被称为创建适当的价值? –

+0

@ Guy-WithA-gum没有。由于它不是一个值,所有的方法都有副作用,所以它将它移出,然后调用析构函数。这根本不涉及prvalues。 –

+0

为什么它只是不返回“a”,为什么它需要从构建值中移走 –

相关问题