.甚至是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;
}
Run Code Online (Sandbox Code Playgroud)
关于标记的行:
值x + y,x*y,x*x,y*y是否可以直接写入d的存储器?或者get_data的返回类型是否可以直接构造在d的内存中?
我想不出不允许这样优化的理由.至少不适用于只有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&) {...}
Run Code Online (Sandbox Code Playgroud)
如果没有第二个功能,它将使得设计更加清晰(函数式编程风格).但有时我只需要修改一个长期存在的Literal对象,并且必须确保我不创建一个新对象并将其复制 - 分配给我想要修改的对象.修改本身很便宜,副本不是 - 这就是我的实验所表明的.
编辑:
假设只允许使用noexcept constexpr构造函数和noexcept默认运算符=的类进行优化.
Jan*_*dec 10
默认复制/移动赋值运算符的删除仅基于一般的as-if规则.也就是说,如果编译器能够确定它对行为没有可观察到的影响,那么编译器就可以这样做.
实际上,as-if规则以一般方式使用,以允许在中间表示和汇编级别进行优化.如果编译器可以内联默认构造函数和赋值,它可以优化它们.它不会使用复制构造函数的代码,但对于它们的默认实现,它应该以相同的代码结束.
编辑:我在有代码示例之前回答.复制/移动构造函数基于对编译器的显式许可而被省略,因此即使它们具有可观察的效果(打印"COPY")也会被省略.分配只能基于as-if规则来省略,但它们具有可观察的效果(打印"ASSIGN"),因此不允许编译器触摸它们.