原则上默认构造函数elision/assignment elision是否可行?

And*_*ler 6 c++ c++11

.甚至是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"),因此不允许编译器触摸它们.