假设我有这种假设的,奇怪的和不直观的情况
#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%的案例中的一个(这是一个实际的假设问题,而不是一个“假设性问题” “)
答案 0 :(得分:5)
复制省略,这是单一的优化,不需要遵循 As-If规则 [#1] ,所以你不应该依赖这种行为。
您可以使用某些编译器设置,例如gcc,来自 man page :
-fno-elide-constructor
C ++标准允许实现省略创建临时文件,该临时文件仅用于初始化相同类型的另一个对象。指定此选项会禁用该优化,并且 迫使G ++在所有情况下调用复制构造函数。
但是,使用它会使您的代码在不同的编译器中不可移植。
[#1] C ++ 03 1.9“程序执行:
符合实现需要模拟(仅)抽象机器的可观察行为。
脚注进一步详细描述了它。
这项规定有时被称为“假设”规则,因为只要结果好像符合要求,实施可以自由地忽视本国际标准的任何要求,只要可以从程序的可观察行为。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。
答案 1 :(得分:3)
标准明确允许RVO / NRVO,通常是Good Thing™,并且几乎没有任何好的设计被它打破,所以没有理由让任何编译器编写者实现这些选项。
我不知道任何允许你根据具体情况将其关闭的编译器。