2

最後の 3 つのオペレーターで RVO を強制する方法:

#include <iostream>

class Noisy {
    private:
        int m_value;
    public:
        Noisy(int value = 0): m_value(value) 
        {
            std::cout << "Noisy(int)\n";
        }
        Noisy(const Noisy& other): m_value(other.m_value)  
        { 
            std::cout << "Noisy(const Noisy&)\n";
        }
        Noisy(Noisy&& other): m_value(other.m_value)
        { 
            std::cout << "Noisy(Noisy&&)\n";
        }
        //~Noisy() {
        //    std::cout << "dtor\n";
        //}
        Noisy operator+(const Noisy& rhs) &
        {
            std::cout << "+(const Noisy&)&\n";
            return Noisy(m_value + rhs.m_value);
        }
        Noisy operator+(Noisy&& rhs) &
        {
            std::cout << "+(Noisy&&)&\n";
            rhs.m_value += m_value;
            return rhs; //std::move(rhs);
        }
        Noisy operator+(const Noisy& rhs) &&
        {
            std::cout << "+(const Noisy&) &&\n";
            this->m_value += rhs.m_value;
            return *this; //std::move(*this);
        }

        Noisy operator+(Noisy&& rhs) &&
        {
            std::cout << "+(Noisy&&) &&\n";
            this->m_value += rhs.m_value;
            return *this; //std::move(*this);
        }
};

int main()
{
    Noisy a, b, c, d, e, f, g;
    Noisy z = a + b + c + d + e + f + g;

    return 0;
}

プログラム実行出力:

Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&) 

またはstd::move、最後の 3 つの演算子で明示的に使用する場合:

Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) && 
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&) 

次のような演算子でコピーしたくない:

Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&

私がこれまでに考え出した唯一の方法は、演算子から参照を返すことですが、これは明らかにぶら下がり参照になります。

新しい g++ を使用して、c++14 および c++17 でコンパイルします。

アップデート

ルールを破ることなく、コンパイラに自分のやりたいことを強制することはできないことを理解しました。
しかし、コンパイラが右辺値をローカルで最適化するためにどのようなイベントが発生するのでしょうか? 次の追加で変更され、結果変数に割り当てられる最初の追加中に単一の右辺値を作成できると思います。

4

1 に答える 1