2

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

    #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 上)你可以告诉编译器不要做任何复制省略。

我的问题是有什么方法可以让编译器不只为这个类使用复制省略吗?

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

4

2 回答 2

5

标准允许复制省略,它是不需要遵循As-If 规则[#1]的单一优化,因此您不应依赖该行为。

您可以使用手册页中的一些编译器设置,例如 gcc :

-fno-elide-constructor

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

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


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

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

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

该规定有时被称为“好像”规则,因为只要从可观察的行为中可以确定,只要结果是好像该要求已被遵守,实施就可以自由地忽略本国际标准的任何要求的程序。例如,如果一个实际的实现可以推断出它的值没有被使用并且没有产生影响程序可观察行为的副作用,那么它就不需要评估表达式的一部分。

于 2012-03-31T16:34:48.923 回答
3

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

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

于 2012-03-31T16:35:55.870 回答