有没有办法在 C++ 编译器中禁用复制省略

Posted

技术标签:

【中文标题】有没有办法在 C++ 编译器中禁用复制省略【英文标题】:Is there a way to disable copy elision in c++ compiler 【发布时间】:2018-06-13 09:50:56 【问题描述】:

在c++98中,下面的程序预计会调用拷贝构造函数。

#include <iostream>

using namespace std;
class A

  public:
    A()  cout << "default" ; 

    A(int i)  cout << "int" ; 


    A(const A& a)  cout << "copy"; 
;

int main ()

   A a1;
   A a2(0);
   A a3 = 0;

  return 0;

如果您在上述情况下显式声明复制构造函数(编译器出错),这一点很明显。但是当复制构造函数未声明为显式时,我看不到它的输出。我想这是因为复制省略。有什么方法可以禁用复制省略或标准是否强制要求它?

【问题讨论】:

复制构造函数应该在哪里调用? 我在 main 函数中看不到复制构造的使用。 gcc-fno-elide-constructors 禁用复制省略 Clang 也有这个标志。 【参考方案1】:

C++ 17

A a3 = 0;

将call 复制构造函数,除非复制被省略。通过-fno-elide-constructors标志

来自C++17,保证复制省略。所以你会 not see 复制构造函数被调用。

【讨论】:

有趣。我的印象是这永远不会调用复制构造函数,即使在 c++11/14 中也是如此。 不,A a3 = 0; will not 在 GCC 上的 C++17 之前的标准中调用复制构造函数。这样做的原因是因为您在编译字符串中包含了标志。 @Ron 我也是这么想的,但是this呢? @Ron 如果A a3 = 0;A a3 = A(0); 会怎样【参考方案2】:

您对复制省略的理解有误。更多信息请参考this question。

在这种特殊情况下,如果显式定义构造函数,则会导致错误,因为A a3 = 0; 在这一行中编译器使用 0 创建了一个对象。

【讨论】:

构造函数为explicit与复制省略无关。 我同意他的理解是错误的(通过 cmets),但他的答案是正确的。

以上是关于有没有办法在 C++ 编译器中禁用复制省略的主要内容,如果未能解决你的问题,请参考以下文章

我们的程序能否在编译时确定它在哪个编译器中编译? [复制]

您如何知道您的编译器支持哪个版本的 ISO C++ 标准? [复制]

有没有办法在 Java 中禁用短路评估?

有没有办法在 C++ 编译时限制数据大小并产生编译错误?

在Qt(或者C++)中,有没有办法得到一个类的变量的名字?

有没有办法将 c++ 编译器标志设为默认值