【问题标题】:Class object creation in C++在 C++ 中创建类对象
【发布时间】:2016-12-29 21:51:11
【问题描述】:

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

假设我们有一些类A 和构造函数A(int a)。有什么区别:

A test_obj(4);

A test_obj = A(4);

?

我通常使用后一种语法,但在我信赖的 C++ 入门书中查找了一些不相关的内容后,我意识到他们通常使用前者。这两者之间的区别经常在内置类型的上下文中讨论(例如int a(6) vs int a = 6),我的理解是在这种情况下它们是等价的。

但是,对于用户定义的类,这两种定义对象的方法是否等效?还是后一种选择先默认构造test_obj,然后使用A的复制构造函数将A(4)的返回值赋给test_obj?如果是第二种可能性,我想这两种方法对于大型类可能会有一些性能差异。

我确信这个问题在互联网上的某个地方得到了回答,即使是在这里,但如果没有找到询问第一个选项和使用 new 之间区别的问题,我无法有效地搜索它,这是不相关的。

【问题讨论】:

  • 我一般使用后一种语法 -- 为什么?你很难找到有经验的 C++ 程序员故意使用这种语法。
  • @PaulMcKenzie 没有特别好的理由,我就是这么做的。我愿意改变。我以前从未真正考虑过。
  • @PaulMcKenzie 回到原来的问题,有什么区别?
  • 我想这两种方法对于大型类可能会有一些性能差异 -- Not necessarily。查看程序集列表中的main

标签: c++ class object


【解决方案1】:

A test_obj = A(4); 在概念上确实构造了一个临时的A 对象,然后从临时对象复制/移动构造test_obj,然后销毁临时对象。

但是,此过程是 copy elision 的候选过程,这意味着编译器可以在验证复制/移动构造函数存在且可访问后将其视为 A test_obj(4);

从 C++17 开始,编译器必须这样做;在此之前它是可选的,但通常编译器会这样做。

【讨论】:

  • 如果A test_obj = A(4);A test_obj = 4; 相同,是否意味着使用explicit specifier 会导致它抛出编译时错误?
  • @UnholySheep 好点。从我的答案中删除了那一点,因为它与 OP 的问题没有真正的关系
  • 显式复制构造函数确实打破了这一点。
  • @UnholySheep:他们不一样。如果构造函数是显式的,那么代码将无法编译。在版本中:A test_obj = 4; 而在A test_obj = A(4); 中没问题
【解决方案2】:

在性能方面这些是等效的,即使您有一个非标准的复制构造函数,如 copy elision 所要求的那样。这是自 C++17 以来得到保证的,但即使在符合早期标准的编译器中也允许并广泛存在。

自己试试,关闭所有优化,强制标准进入 C++11(或 C++03,更改右上角的命令行): https://godbolt.org/g/GAq7fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多