为什么声明对象时不执行构造函数和赋值运算符?

发布于 2024-10-09 08:11:36 字数 1154 浏览 0 评论 0原文

测试程序的

#include <iostream>
using namespace std;

class A
   {public:
       A (): I(0) {cout << "default construcot" << endl; };
       explicit A (int i): I(i) {cout << "another construcot" << endl; };
       A (const A& a): I(a.I) {cout << "copy constructor" << endl; }
       A& operator = (const A& a)
          {cout << "assignment operator" << endl; 
           if (this == &a) return *this; 
           I = a.I;
           return *this; 
          }
       void show () {cout << I << endl; };
    private:
       int I;
   };

int main ()
   {A a = A(1);
    A b;
    b = A(2);
    a.show();
    b.show();
    return 0;
   }

输出

another construcot
default construcot
another construcot
assignment operator
1
2

显示,与“b”不同,对象“a”是“直接”从 A(1) 构造的,而不执行赋值运算符。但复制构造函数也没有执行。为什么?在这种情况下有没有办法强制执行赋值运算符?如果我写的话,我会期望这种行为,

A a (1);

但我希望

A a = A(1);

它必须与第一种情况不同。或不?

(事实上​​,当我有一个从 A 派生的类 B 并希望 A 的赋值运算符处理像 A a = B(...) 这样的声明时,就会出现问题。)

The test program is

#include <iostream>
using namespace std;

class A
   {public:
       A (): I(0) {cout << "default construcot" << endl; };
       explicit A (int i): I(i) {cout << "another construcot" << endl; };
       A (const A& a): I(a.I) {cout << "copy constructor" << endl; }
       A& operator = (const A& a)
          {cout << "assignment operator" << endl; 
           if (this == &a) return *this; 
           I = a.I;
           return *this; 
          }
       void show () {cout << I << endl; };
    private:
       int I;
   };

int main ()
   {A a = A(1);
    A b;
    b = A(2);
    a.show();
    b.show();
    return 0;
   }

the output

another construcot
default construcot
another construcot
assignment operator
1
2

shows, that object 'a' unlike 'b' was constructed from A(1) "directly" without execution of assignment operator. But copy constructor wasn't executed too. Why? Is there a way to force execution of assignment operator in this case? I would expected such behavior if I wrote

A a (1);

but I want

A a = A(1);

which have to differs from first case. Or not?

(In fact, the problem appears when I have a class B derived from A and want A's assignment operator to handle declaration like A a = B(...).)

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

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

发布评论

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

评论(5

善良天后 2024-10-16 08:11:36

A a = A(1);

与此不同:

A a;
a = A(1);

在第二种情况下 = 是运算符,在第一种情况下 = 不是运算符。在第一个语句中,它是初始化语法。编译器可能会调用复制构造函数,但它可以对其进行优化,因为它是语言允许的地方之一(RVO、异常抛出等)。

This

A a = A(1);

is not equivalent to this:

A a;
a = A(1);

In the second case = is an operator, in the first case = is not an operator. In the first statement it's an initialization syntax. The compiler may call copy constructor, but it can optimize it out as it's one of the places where it's allowed by the language (RVO, exception throw, etc...).

人海汹涌 2024-10-16 08:11:36

为什么

该标准允许编译器优化复制构造。这不是一个赋值,因为它是声明的一部分(因此,如果没有进行优化,它将产生一个临时对象,然后将临时对象复制构造到 a 中)。

在这种情况下有没有办法强制执行赋值运算符。

这取决于您的编译器。但我不知道有什么可以让你强制执行此操作(但我从未尝试过将其关闭)。尝试关闭编译器正在执行的所有优化。

如果我写:A a (1);,我会期望这样的行为;

该标准明确指出您的版本可以对此进行优化。

我有一个从 A 派生的类 B,并且希望 A 的赋值运算符处理像 A a = B(...) 这样的声明。)

如果这样做,您将切片 B 并只分配 B 对象的 A 部分。
您想使用参考吗?

A const& a = B();

Why

The standard allows the compiler to optimize away the copy construction. Not this is NOT an assignment as it is part of the declaration (so if the optimization was not done it would result in a temporary object and then a copy construction of the temporary into a).

Is there a way to force execution of assignment operator in this case.

That will depend on your compiler. But I don not know of any that would allow you to force this (but then I have never tried turning it off). Try turning off all optimizations that your compiler is doing.

I would expected such behavior if I wrote: A a (1);

The standard explicitly states that your version can be optimized into this.

I have a class B derived from A and want A's assignment operator to handle declaration like A a = B(...).)

If you do that you will slice the B and just assign the A part of the B object.
Do you want to use a reference?

A const& a = B();
舟遥客 2024-10-16 08:11:36

为什么?因为编译器可以很自由地这样做,而且大多数编译器都这样做。

你能强迫吗?不。

Why? Because the compiler is quite free to do so and most do.

Can you force it? No.

江南月 2024-10-16 08:11:36

语言中明确定义编译器基本上可以在任何需要的时候删除复制结构,并且第一种形式无论如何都是初始化语法。但是,您可能会发现,当您使用实际的派生实例调用它时,此行为会被删除,因为这样做会影响程序的正确性。

It's explicitly defined in the language that the compiler may remove copy constructions basically whenever it wants to, and the first form is initialization syntax anyway. However you will likely find that this behaviour is removed for when you call it with an actual derived instance as doing so would affect the correctness of your program.

北方的巷 2024-10-16 08:11:36

我希望 A a(1);A a = 1; 是严格相同的东西,这是由标准保证的。

I hope A a(1); and A a = 1; is strictly the same thing, it is guaranteed by standard.

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