C++ "send"临时值如何按值起作用?

  • 本文关键字:何按值 起作用 send C++ c++
  • 更新时间 :
  • 英文 :


我有一个简单的片段:

class Object
{
private:
int value;
public:
Object(int value) : value(value) { cout << "Object::ctorn"; }
Object(const Object& obj) { cout << "Object::copy-ctorn"; }
Object(Object&& obj) { cout << "Object::move-ctorn"; }
};
Object take_and_return_obj(Object o) { return o; }
int main()
{
Object o(5);
take_and_return_obj(o);
}

现在,正如预期的那样,打印一个copymove构造函数。

Object::copy-ctor
Object::move-ctor

这是因为使用copy-ctoro被复制到函数,然后被回收使用以来move-ctor函数,返回值是一个xvalue。

但是,当函数的初始参数也是一个xvalue时,会发生一些事情:

int main()
{
Object o = take_and_return_obj(Object(5));
}

结果是,当值被发送给函数时,什么也没发生:

Object::ctor
Object::move-ctor

我假设move用于返回操作,因此不受此更改的影响。但是,没有调用复制函数来在函数范围内创建0。我知道它不是任何类型的指针或引用,因为我让函数按值接受参数。

所以我的问题是:我在main中创建的xvalue究竟发生了什么,以便函数内的参数得到它的值?

这是一个更有教育意义的问题,所以不要害怕进行更深入的回答。

是,在take_and_return_obj(Object(5));中,省略了构造参数o的复制/移动操作;

在下列情况下,编译器被要求省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象直接构造到存储中,否则它们将被复制/移动到存储中。复制/移动构造函数不需要存在或可访问:

  • ……

  • …在对象的初始化中,当初始化表达式是与变量类型相同的类类型(忽略cv-限定)的右值时:

    T x = T(T(f())); // only one call to default constructor of T, to initialize x
    

这个答案是为那些不知道术语"复制-省略"的人准备的。

这个问题由这个答案(包括两个相连的答案)回答。

在某些情况下,编译器可能会忽略复制内容。这种情况包括从函数获取或返回x值等场景。在这些情况下,不会调用copy/move函数,这样就不会创建对象的额外副本。