3

右辺値参照について読んだばかりで、以下は私が参照しているコードです

vector<string> v;
string s = "hello";   

v.push_back(s); 
cout << s << endl;
cout << v[0] << endl;
return 0

私の質問は、これまで、オブジェクト (または文字列) のベクトルを見たときはいつでも、ほとんどの場合、上記のように挿入が行われていることです。代わりに、v.push_back(std::move(s))重複したオブジェクトを不必要に作成することはありません。

これは、オブジェクトを STL に追加する正しい方法である必要があります。関心があるのはコンテナー内のデータだけであり、それ以外の場合は変数ではありません。

4

2 に答える 2

5

私が得たコメントを考慮して、この回答に対する別のアプローチを決定しました。これは、ベクトルにオブジェクトを追加するさまざまな方法を使用するプログラムです。このプログラムは、どのコピー コンストラクター、ムーブ コンストラクター、コピー オペレーター、ムーブ オペレーター、およびデストラクターがすべての場合に呼び出されるかを正確に出力します。

このプログラムは素晴らしいfmt ライブラリを使用しています。そしてfmt::print、あなたが思っていることを正確に行います。おそらく、使用する必要があります::fmt。一般に、オブジェクトから移動すると、オブジェクトは未指定 ( undefinedとは異なることに注意) 状態になることに注意してください。もちろん、自分で書いたクラスについては、それがどのような状態にあるかを正確に知っています。しかし、標準ライブラリのクラスや他の人が書いたクラスについては、わかりません。どうやら、標準ライブラリ クラスの場合、状態を既知の状態に設定するために何かを行うと、オブジェクトが実際にその状態に変更されることが保証されています。

個人的には、オブジェクトから移動した後の唯一の有効な操作は、そのデストラクタを呼び出すことであるかのようにオブジェクトを扱います。しかし、何らかの方法で単にストレージを再利用したい場合もあります。

プログラムは次のとおりです。

#include <fmt/core.h> // fmt
#include <vector>  // vector
#include <utility> // move

class TestClass {
 public:
    TestClass(int a, int b) {
        fmt::print("TestClass{{{}, {}}}\n", a, b);
    }
    TestClass(TestClass const &) noexcept {
        fmt::print("TestClass{{TestClass const &}}\n");
    }
    TestClass(TestClass &&) noexcept {
        fmt::print("TestClass{{TestClass &&}}\n");
    }
    TestClass const &operator =(TestClass const &) noexcept {
        fmt::print("=(TestClass const &)\n");
        return *this;
    }
    TestClass const &operator =(TestClass &&) noexcept {
        fmt::print("=(TestClass &&)\n");
        return *this;
    }
    ~TestClass() noexcept {
        fmt::print("~TestClass()\n");
    }
};

int main()
{
   ::std::vector<TestClass> v;
   // Reserve necessary space so movements of vector elements doesn't clutter up
   // the output.
   v.reserve(6);
   fmt::print("Constructing initial\n");
   TestClass o{1, 2};

   fmt::print("\bv.push_back(o)\n");
   v.push_back(o);

   fmt::print("\nv.push_back(::std::move(o))\n");
   v.push_back(::std::move(o));

   fmt::print("\nv.push_back(TestClass{{3, 4}})\n");
   v.push_back(TestClass{3, 4});

   fmt::print("\nv.emplace_back(5, 6)\n");
   v.emplace_back(5, 6);

   fmt::print("\nv.emplace_back(::std::move(o))\n");
   v.emplace_back(::std::move(o));

   fmt::print("\nv.emplace_back(TestClass{{5, 6}})\n");
   v.emplace_back(TestClass{5, 6});

   fmt::print("\nHere H\n");
}

プログラムの出力は次のとおりです。

Constructing initial
TestClass{1, 2}
v.push_back(o)
TestClass{TestClass const &}

v.push_back(::std::move(o))
TestClass{TestClass &&}

v.push_back(TestClass{3, 4})
TestClass{3, 4}
TestClass{TestClass &&}
~TestClass()

v.emplace_back(5, 6)
TestClass{5, 6}

v.emplace_back(::std::move(o))
TestClass{TestClass &&}

v.emplace_back(TestClass{5, 6})
TestClass{5, 6}
TestClass{TestClass &&}
~TestClass()

Here H
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()

このプログラムはまさに私が期待した出力を持っており、その出力は(私の知る限り)以前にここで得た答えと一致していると言えます。


::std::代わりに使用する理由std::

于 2019-01-27T17:19:04.147 に答える