在AIX上使用xlC编译以下内容会导致打印“2 2”的代码。在使用gcc和clang的Linux上,它可靠地生成“3 3”。
#include <iostream>
struct Numbers
{
Numbers() : a(0) , b(0) { }
Numbers(int a, int b) : a(a), b(b) { }
int a;
int b;
};
Numbers combine(const Numbers& a, const Numbers& b)
{
Numbers x;
x.a = a.a + b.a;
x.b = a.b + b.b;
return x;
}
Numbers make()
{
Numbers a(1, 1);
Numbers b(2, 2);
a = combine(a, b);
return a;
}
int main()
{
Numbers a = make();
std::cerr << a.a << " " << a.b << "\n";
}
在我看来,AIX正在将RVO应用于combine
的返回值,因此当我创建Numbers x
时,它最终会使用默认的初始值{{}覆盖我的参数a
。 1}}。
我在这里调用了一些未定义的行为吗?我希望在评估x
并将其分配给a
之前,不会对combine(a, b)
进行任何修改。
这是: IBM XL C / C ++ for AIX,V12.1(5765-J02,5725-C72) 版本:12.01.0000.0012
答案 0 :(得分:3)
看起来编译器正在复制赋值(!)上执行复制省略,它实际上只能在初始化时执行。也就是说,在初始化a
时,编译器确实覆盖了与参数x
关联的对象。将RVO(对于某些RVO定义)应用于combine
的返回值本身并没有错。错误的是RVO的目标(在make
范围内应该是暂时的,而不是a
中与make
相关联的对象。
添加用户提供的副本分配运算符应该可以解决方法:
Numbers &operator=(const Numbers &other) { a = other.a; b = other.b; return *this; }