C++中的类对象创建

3

我有一个基础的C++问题,我应该知道答案。

假设我们有一个类A,并且有一个构造函数A(int a)。以下两种方式有什么不同:

A test_obj(4);

并且

A test_obj = A(4);

?

我通常使用后一种语法,但在查阅我的可靠的C ++入门指南时,我意识到他们通常使用前者。这两者之间的区别通常在内置类型(例如,int a(6)int a = 6)的上下文中讨论,我的理解是,在这种情况下它们是等效的。
然而,在用户定义类的情况下,定义对象的这两种方法是否等效?还是后一种选项首先默认构造test_obj,然后使用A的复制构造函数将A(4)的返回值分配给test_obj?如果是第二种可能性,我想对于大型类,这两种方法之间可能存在某些性能差异。
我相信这个问题在互联网上的某个地方已经得到了回答,甚至在这里也有,但我无法有效地搜索到它,而不是找到问第一个选项和使用new之间的区别的问题,这是无关的。

2
我通常使用后一种语法。为什么呢?你很难找到一个有经验的C++程序员会故意使用那种语法。 - PaulMcKenzie
@PaulMcKenzie 没有特别好的理由,我只是这样做。我愿意改变。以前我从来没有真正考虑过这个问题。 - The Wind-Up Bird
@PaulMcKenzie 回到原始问题,有什么区别? - jacknad
“我想对于大型类,这两种方法之间可能会存在一些性能差异” - 不一定。请查看汇编清单中的 main - PaulMcKenzie
2个回答

4
A test_obj = A(4);的概念确实会构造一个临时的A对象,然后从临时对象复制/移动构造test_obj,最后销毁临时对象。
然而,这个过程可以使用复制省略进行优化,这意味着编译器可以在验证复制/移动构造函数存在并可访问后将其视为A test_obj(4);
从C++17开始,编译器必须执行这个优化;在此之前是可选的,但通常编译器都会执行。

1
如果 A test_obj = A(4);A test_obj = 4; 是相同的,那么使用 explicit 说明符会导致编译时错误吗? - UnholySheep
@UnholySheep 说得好。我从答案中删除了那一部分,因为它与 OP 的问题没有真正的关系。 - M.M
显式复制构造函数确实让我出了问题。 - The Vee
@UnholySheep:它们不同。如果构造函数是显式的,则代码不会编译。在版本 A test_obj = 4; 中,它是正确的,在 A test_obj = A(4); 中也是正确的。 - Raindrop7

3

就性能而言,即使您有一个非标准的复制构造函数(如复制省略所规定),这些对象也是等效的。自C++17起,这是有保证的,但即使在符合早期标准的编译器中也是允许和广泛存在的。

尝试一下,关闭所有优化并将标准强制为C++11(或C++03,在右上角更改命令行): https://godbolt.org/g/GAq7fi


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接