. 甚至是 C++11 标准允许的?
如果是这样,是否有任何编译器可以真正做到这一点?
这是我的意思的一个例子:
template<class T> //T is a builtin type
class data
{
public:
constexpr
data() noexcept :
x_{0,0,0,0}
{}
constexpr
data(const T& a, const T& b, const T& c, const T& d) noexcept :
x_{a,b,c,d}
{}
data(const data&) noexcept = default;
data& operator = (const data&) noexcept = default;
constexpr const T&
operator[] (std::size_t i) const noexcept {
return x_[i];
}
T&
operator[] (std::size_t i) noexcept {
return x_[i];
}
private:
T x_[4];
};
template<class Ostream, class T>
Ostream& operator << (Ostream& os, const data<T>& d)
{
return (os << d[0] <<' '<< d[1] <<' '<< d[2] <<' '<< d[3]);
}
template<class T>
inline constexpr
data<T>
get_data(const T& x, const T& y)
{
return data<T>{x + y, x * y, x*x, y*y};
}
int main()
{
double x, y;
std::cin >> x >> y;
auto d = data<double>{x, y, 2*x, 2*y};
std::cout << d << std::endl;
//THE QUESTION IS ABOUT THIS LINE
d = get_data(x,y);
d[0] += d[2];
d[1] += d[3];
d[2] *= d[3];
std::cout << d << std::endl;
return 0;
}
关于标记线:
值 x+y, x*y, x*x, y*y 是否可以直接写入 d 的内存?还是直接在d的内存中构造get_data的返回类型?
我想不出不允许这种优化的理由。至少对于只有 constexpr 构造函数和默认复制和赋值运算符的类来说不是。
g++ 4.7.2 省略了本例中的所有复制构造函数;然而,似乎总是执行分配(即使仅用于默认分配 - 据我从 g++ 发出的程序集中可以看出)。
我提出问题的动机是以下情况,在这种情况下,这种优化将大大简化和改进库设计。假设您使用文字类编写性能关键的库例程。该类的对象将保存足够的数据(例如 20 个双精度数据),因此必须将副本保持在最低限度。
class Literal{ constexpr Literal(...): {...} {} ...};
//nice: allows RVO and is guaranteed to not have any side effects
constexpr Literal get_random_literal(RandomEngine&) {return Literal{....}; }
//not favorable in my opinion: possible non-obvious side-effects, code duplication
//would be superfluous if said optimization were performed
void set_literal_random(RandomEngine&, Literal&) {...}
如果我可以不使用第二个函数,它将使设计更加简洁(函数式编程风格)。但有时我只需要修改一个长期存在的 Literal 对象,并且必须确保我没有创建一个新对象并将其复制分配给我想要修改的对象。修改本身很便宜,而副本则不便宜——这就是我的实验所表明的。
编辑:
假设只允许具有 noexcept constexpr 构造函数和 noexcept 默认 operator= 的类进行优化。