复制省略导致不同的结果

时间:2012-03-31 16:32:47

标签: c++ copy-elision

假设我有这种假设的,奇怪的和不直观的情况

    #include <iostream>

    struct A
    {
      A()
      {
        member = 1;
      }

      A(const A &)
      {
        member = 2;
      }

      int member;
    };

    int main()
    {
      A a = A();
      A b = a;
      std::cout << a.member << std::endl;
      std::cout << b.member << std::endl;
      return 0;
    }

我知道复制省略意味着a将仅使用默认构造函数进行初始化,并且b将使用复制构造函数进行初始化。我也知道(至少在gcc上)你可以告诉编译器不要做任何复制省略。

我的问题是,有一些方法让编译器不使用copy elision 仅用于此类吗?

我意识到在任何实际情况下的答案都是99.9%的时间找到其他方式,而我没有0.01%的案例中的一个(这是一个实际的假设问题,而不是一个“假设性问题” “)

2 个答案:

答案 0 :(得分:5)

标准允许

复制省略,这是单一的优化,不需要遵循 As-If规则 [#1] ,所以你不应该依赖这种行为。

您可以使用某些编译器设置,例如gcc,来自 man page

-fno-elide-constructor

  

C ++标准允许实现省略创建临时文件,该临时文件仅用于初始化相同类型的另一个对象。指定此选项会禁用该优化,并且   迫使G ++在所有情况下调用复制构造函数。

但是,使用它会使您的代码在不同的编译器中不可移植。


[#1] C ++ 03 1.9“程序执行:

  

符合实现需要模拟(仅)抽象机器的可观察行为。

脚注进一步详细描述了它。

  

这项规定有时被称为“假设”规则,因为只要结果好像符合要求,实施可以自由地忽视本国际标准的任何要求,只要可以从程序的可观察行为。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。

答案 1 :(得分:3)

标准明确允许RVO / NRVO,通常是Good Thing™,并且几乎没有任何好的设计被它打破,所以没有理由让任何编译器编写者实现这些选项。

我不知道任何允许你根据具体情况将其关闭的编译器。