C++ 为什么在以下程序中不调用复制构造函数?

C++ 为什么在以下程序中不调用复制构造函数?,c++,C++,可能重复: 考虑以下代码段: #include <iostream> using namespace std; class Test { char name[16]; public: Test () { cout <<"Inside Constructor"<<endl; } Test (const Test & t)

可能重复:

考虑以下代码段:

#include <iostream>

using namespace std;

class Test
{
        char name[16];
        public:
        Test ()
        {
                cout <<"Inside Constructor"<<endl;
        }

        Test (const Test & t)
        {
                cout <<"Inside Copy Constructor "<<endl;
        }

};

Test f()
{
        return Test();
}

int main ( int argc, char ** argv)
{
        Test t;
        Test t1 = f();

}

我的理解有什么问题?

因为删除了所需的额外副本。

因为删除了所需的额外副本。

它被调用。

它被调用。

我想你从来没有调用过副本构造函数。调用默认构造函数,获取临时副本,然后调用赋值运算符

编辑。好的,我读错了测试t1=f;。RVO实际上很可能是踢进了f。 所以它本质上等于Test t1=Test


我认为这是允许应用的一些优化,即使它会导致程序行为的改变。如果您弄乱了优化标志,您可能会让它在旧对象上执行复制构造函数+析构函数。

我想您永远不会调用复制构造函数。调用默认构造函数,获取临时副本,然后调用赋值运算符

编辑。好的,我读错了测试t1=f;。RVO实际上很可能是踢进了f。 所以它本质上等于Test t1=Test

我认为这是允许应用的一些优化,即使它会导致程序行为的改变。如果您弄乱了优化标志,您可能会让它在旧对象上执行复制构造函数+析构函数。

这里出现两个复制省略

第一种是返回值优化,而不是将表达式测试的结果复制到临时对象(即f的返回值)中,表达式测试通过直接构造到临时对象(即f的返回值)中进行评估

第二个是从t1的初始值设定项表达式到t1本身的复制,因此不是将f的返回值临时复制到t1中,而是将f的返回值临时直接构造到t1中

这两个省略链接在一起-因此,在构造f的返回值时,t1的内存用作目标,在构造测试时,f的返回值的内存用作目标。因此,实际上t1是由no args构造函数直接初始化的,不需要拷贝

复制构造函数省略在C++03的12.8/15和C++11的12.8/31标准中定义,这也允许省略移动。它需要特定的权限,因为它改变了程序的可观察行为。在您的情况下,它忽略了复制构造函数的副作用,即输出。因此,只能在标准中规定的条件下执行

这两个省略都是C++03中第二个允许省略的示例,C++11中第三个允许省略,当源代码是临时的时

第一个允许的省略通常称为命名返回值优化,它允许在源不是临时的情况下省略特定类型的副本。

这里出现两个副本省略

第一种是返回值优化,而不是将表达式测试的结果复制到临时对象(即f的返回值)中,表达式测试通过直接构造到临时对象(即f的返回值)中进行评估

第二个是从t1的初始值设定项表达式到t1本身的复制,因此不是将f的返回值临时复制到t1中,而是将f的返回值临时直接构造到t1中

这两个省略链接在一起-因此,在构造f的返回值时,t1的内存用作目标,在构造测试时,f的返回值的内存用作目标。因此,实际上t1是由no args构造函数直接初始化的,不需要拷贝

复制构造函数省略在C++03的12.8/15和C++11的12.8/31标准中定义,这也允许省略移动。它需要特定的权限,因为它改变了程序的可观察行为。在您的情况下,它忽略了复制构造函数的副作用,即输出。因此,只能在标准中规定的条件下执行

这两个省略都是C++03中第二个允许省略的示例,C++11中第三个允许省略,当源代码是临时的时

第一个允许的省略通常称为命名返回值优化,它允许在源不是临时的情况下省略特定类型的副本

Inside Constructor
Inside Constructor