51

次のコードがあるとしましょう。

std::vector<int> f()
{
  std::vector<int> y;
  ...
  return y;
} 

std::vector<int> x = ...
x = f();

ここでは、コンパイラには2つのアプローチがあるようです。

(a)NRVO:xを破棄してから、xの代わりにf()を作成します。
(b)移動:一時空間でf()を構築し、f()をxに移動し、f()を破棄します。

標準によれば、コンパイラはどちらのアプローチも自由に使用できますか?

4

1 に答える 1

60

コンパイラーは、一時空間にNRVOするか、構成を一時空間に移動することができます。そこから、assignを移動しxます。

アップデート:

右辺値参照を使用して最適化する必要があり、結果に満足できない場合は、その状態を追跡するサンプルクラスを自分で作成してください。

  • 構築された
  • デフォルトで構築
  • から移動
  • 破壊された

そして、そのクラスをテストで実行します。例えば:

#include <iostream>
#include <cassert>

class A
{
    int state_;
public:
    enum {destructed = -2, moved_from, default_constructed};

    A() : state_(default_constructed) {}
    A(const A& a) : state_(a.state_) {}
    A& operator=(const A& a) {state_ = a.state_; return *this;}
    A(A&& a) : state_(a.state_) {a.state_ = moved_from;}
    A& operator=(A&& a)
        {state_ = a.state_; a.state_ = moved_from; return *this;}
    ~A() {state_ = destructed;}

    explicit A(int s) : state_(s) {assert(state_ > default_constructed);}

    friend
    std::ostream&
    operator<<(std::ostream& os, const A& a)
    {
        switch (a.state_)
        {
        case A::destructed:
            os << "A is destructed\n";
            break;
        case A::moved_from:
            os << "A is moved from\n";
            break;
        case A::default_constructed:
            os << "A is default constructed\n";
            break;
        default:
            os << "A = " << a.state_ << '\n';
            break;
        }
        return os;
    }

    friend bool operator==(const A& x, const A& y)
        {return x.state_ == y.state_;}
    friend bool operator<(const A& x, const A& y)
        {return x.state_ < y.state_;}
};

A&& f()
{
    A y;
    return std::move(y);
}

int main()
{
    A a = f();
    std::cout << a;
}

役立つ場合は、関心のある特別なメンバー(たとえば、コピーコンストラクター、移動コンストラクターなど)にprintステートメントを配置します。

ところで、これがあなたに失敗したとしても、心配しないでください。それは私にとってもセグフォールトです。したがって、この特定の設計(ローカル変数への右辺値参照を返す)は適切な設計ではありません。システムでは、segfaultingの代わりに、「Aisdestructed」と出力される場合があります。これは、これを実行したくないという別の兆候です。

于 2011-06-04T00:36:41.410 に答える