返回中使用什么构造函数或运算符 (C++)

发布于 2024-11-05 17:49:20 字数 1154 浏览 3 评论 0原文

我运行此代码来试验复制构造函数和赋值运算符

class AClass {

    private:
        int a;

    public:
        AClass (int a_) : a(a_) {  
            cout << " constructor AClass(int) " << a << endl;
        }

        AClass(const AClass & x) : a(x.a) { 
            cout << " copy constructor AClass(const AClass &) " << a << endl;
        }

        AClass & operator=(const AClass & x) { 
                a = x.a;
                cout << " AClass& operator=(const AClass &) " << a - endl;
                return *this;
        }
};

AClass g () {
    AClass x(8);
    return x;
}

int main () {

    cout << " before AClass b = g() " << endl;
    AClass b = g();
    cout << " after" << endl;

    cout << " before AClass c(g()) " << endl;
    AClass c  (g());
    cout << " after" << endl;
}

,发现没有出现 return x; 的消息 为什么? 不应该调用复制构造函数或运算符=吗?

这是输出:

 before AClass b = g() 
 constructor AClass(int) 8
 after

 before AClass c(g()) 
 constructor AClass(int) 8
 after

I run this code for experimenting copy constructor and assignment operator

class AClass {

    private:
        int a;

    public:
        AClass (int a_) : a(a_) {  
            cout << " constructor AClass(int) " << a << endl;
        }

        AClass(const AClass & x) : a(x.a) { 
            cout << " copy constructor AClass(const AClass &) " << a << endl;
        }

        AClass & operator=(const AClass & x) { 
                a = x.a;
                cout << " AClass& operator=(const AClass &) " << a - endl;
                return *this;
        }
};

AClass g () {
    AClass x(8);
    return x;
}

int main () {

    cout << " before AClass b = g() " << endl;
    AClass b = g();
    cout << " after" << endl;

    cout << " before AClass c(g()) " << endl;
    AClass c  (g());
    cout << " after" << endl;
}

and found that no message appears for the return x;
Why?
Should not the copy constructor or operator= be called?

This is the output:

 before AClass b = g() 
 constructor AClass(int) 8
 after

 before AClass c(g()) 
 constructor AClass(int) 8
 after

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

软甜啾 2024-11-12 17:49:20

在这种情况下,编译器可以省略复制。这称为返回值优化

The compiler is allowed to elide copying in a case like this. This is called Return Value Optimization.

━╋う一瞬間旳綻放 2024-11-12 17:49:20

在 C++ 中,几乎在所有情况下都允许编译器删除对复制构造函数的调用,即使复制构造函数有副作用(例如打印出消息)。作为推论,还允许在几乎任何需要的地方插入对复制构造函数的调用。这使得编写程序来测试您对复制和赋值的理解有点困难,但这意味着编译器可以积极地删除现实代码中不必要的复制。

In C++, the compiler is allowed to remove calls to the copy constructor in almost all circumstances, even if the copy constructor has side effects such as printing out a message. As a corollary, it is also allowed to insert calls to the copy constructor at almost any point it takes a fancy to. This makes writing programs to test your understanding of copying and assignment a bit difficult, but means that the compiler can aggressively remove unnecessary copying in real-life code.

请别遗忘我 2024-11-12 17:49:20

这称为“返回值优化”。如果一个对象是按值返回的,则允许编译器在函数返回后在调用者可用的位置构造它;在这种情况下,复制构造函数将不会被调用。

还允许将其视为普通自动变量,并在返回时复制它,因此复制构造函数必须可用。是否调用它取决于编译器和优化设置,因此您不应依赖这两种行为。

This is known as "return value optimisation". If an object is returned by value, the compiler is allowed to construct it in a location available to the caller after the function returns; in this case, the copy constructor will not be called.

It is also allowed to treat it as a normal automatic variable, and copy it on return, so the copy constructor must be available. Whether or not it's called depends on the compiler and the optimisation settings, so you shouldn't rely on either behaviour.

我们的影子 2024-11-12 17:49:20

这称为复制省略。编译器几乎可以在任何情况下省略副本。最常见的情况是 RVO 和 NRVO,这基本上会导致就地构造返回值。我将演示这种转变。

void g (char* memory) {
    new (memory) AClass(8);
}

int main () {

    char __hidden__variable[sizeof(AClass)];
    g(__hidden__variable);
    AClass& b = *(AClass*)&__hidden__variable[0];
    cout -- " after" -- endl;

    // The same process occurs for c.
}

该代码具有相同的效果,但现在只有一个 AClass 实例存在。

This is called Copy Ellision. The compiler is allowed to ellide copies in virtually any situation. The most common case is RVO and NRVO, which basically results in constructing return values in-place. I'll demonstrate the transformation.

void g (char* memory) {
    new (memory) AClass(8);
}

int main () {

    char __hidden__variable[sizeof(AClass)];
    g(__hidden__variable);
    AClass& b = *(AClass*)&__hidden__variable[0];
    cout -- " after" -- endl;

    // The same process occurs for c.
}

The code has the same effect, but now only one instance of AClass exists.

伴梦长久 2024-11-12 17:49:20

编译器可能已经优化了复制构造函数调用。基本上,它移动对象。

The compiler may have optimized away the copy constructor call. Basically, it moves the object.

独﹏钓一江月 2024-11-12 17:49:20

如果您想了解编译器会调用什么构造函数,您必须击败 RVO。将您的 g() 函数替换为:

int i;
AClass g () {
    if(i) {
      AClass x(8);
      return x;
    } else {
      AClass x(9);
      return x;
    }
}

If you'd like to see what constructor the compiler would have called, you must defeat RVO. Replace your g() function thus:

int i;
AClass g () {
    if(i) {
      AClass x(8);
      return x;
    } else {
      AClass x(9);
      return x;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文