2017-10-23 7 views
4

私は、次のコードを得た:私は、ベクターでのWorkersFactory格納を持っている(Code Live: C++ ShellC++オブジェクトはstd :: movedを取得しませんか?

class Worker 
{ 
public: 
    Worker (std::string name):_name (name) {}; 

    Worker (const Worker & worker):_name (worker._name) 
    { std::cout << _name << " got copied!" << std::endl; } 

    Worker (Worker && other):_name (other._name) 
    { std::cout << _name << " got moved!" << std::endl; } 

    ~Worker() 
    { std::cout << _name << " got destroyed!" << std::endl; } 

    void changeName(std::string name) 
    { this->_name = name; } 

private: 
    std::string _name; 
}; 

class Factory 
{ 
public: 
    Factory() 
    { std::cout << "Factory got created!" << std::endl; } 

    ~Factory() 
    { std::cout << "Factory got destroyed!" << std::endl; } 

    void addWorker (Worker & worker) 
    { this->workers.push_back (std::move (worker)); } 

    Worker & getLastWorker() 
    { this->workers.back(); } 

private: 
    std::vector <Worker> workers; 
}; 
int main() 
{ 
    auto factory = std::make_unique <Factory>(); 
    Worker w1 ("Bob"); 
    factory->addWorker (w1); 
    Worker & workerRef = factory->getLastWorker(); 
    //workerRef.changeName("Mary"); 

    return 0; 
} 

を。私はmain()を実行すると、私は次のような出力を得る:

Factory got created! 
Bob got moved! 
Bob got destroyed! 
Factory got destroyed! 
Bob got destroyed! 

をしかし、私はWorker w1Factoryにベクトルworkersに移動します思ったようBob got destroyed!が、2回表示されますなぜ周り私の頭を取得することはできません。また、workerRef.changeName("Mary");にコメントすると、コードがSegmentation faultでクラッシュします。

私は今月1ヶ月間C++でコーディングしており、ここで本当に苦労しています。私はしばらくの間グーグルで探せましたが、ヒントが見つからないので、どんな助けも素晴らしいです!

+0

ここから移り変わる何かへの参照は、非常に驚​​くべきインターフェイスのように感じます。この選択の理由はありますか? –

+0

私はhttps://youtu.be/cO1lb2M​​iDr8?t=30m46sを見て、彼はどこにstd :: moveをpush_back()内のstd :: vectorで動かすことを提案しました。それは私がそれを試した唯一の理由です。 – DummySenior

答えて

6

は(そのように実装されていれば、それだけでコピーできます)オブジェクトの内容を移動することを予告してください。元のオブジェクトが消えてしまうということではなく、値が変更される可能性があります。 、

  1. Worker w1 ("Bob");
  2. this->workers.push_back (std::move (worker));

秒(とにかく、それの顔に)最初から勇気を盗む:

あなたの例では、2つの場所でオブジェクトを作成します最初はまだ生きています。そして、生きているオブジェクトは、その生涯の終わりに呼び出されるデストラクタを持ちます(w1の場合、それはmainの終了です)。

+0

元のオブジェクトを消滅させる方法はありますか?つまり、実際に移動するように、ここにムーブコンストラクタを実装する方法があります。 –

+2

@ GauravSehgal - いいえオブジェクトは、ある値を持つストレージの領域です。プログラマは値を変更することができますが、デストラクタが呼び出されるまで記憶領域はオブジェクトのままです。それを回避することはありません。 – StoryTeller

+0

@ GauravSehgal - 移動元のストリングのデストラクタは、ポインタがヌルであるかどうかをテストしてから何もしません。 –

0

単純です:

空のオブジェクトデストラクタも呼び出されます。

move constractorで古いオブジェクトは新しいオブジェクトにそのコンテンツ(特にポインタ)を転送して空になり、空のオブジェクトとしてスコープの終わりで破棄されました。

は、元はもうボブと呼ばれていないはず移動コンストラクタの後に...のみ移動

0

まず、あなたの移動コンストラクタは実際にはになりません。を移動すると、文字列がコピーされます。

Workerをベクターにプッシュバックすると、2つのWorkerオブジェクトが残ります.1つはmain関数内にあり、もう1つはベクター内にあります。これらのオブジェクトの両方を破壊する必要があります。

4

まだ2つのオブジェクトがあります.1つはmainに、もう1つはベクターの内側にあります。

「移動」は実際にオブジェクトを移動するのではなく、そのコンテンツのみを少なくとも概念的に(std::moveは型キャストのみです)。
"move constructor"がコピーコンストラクタとまったく同じように振る舞うように、あなたのケースのように、何かが動くケースは必ずしもありません。

さらに "move-y"移動コンストラクタが必要な場合は、:_name (std::move(other._name))と書くと、w1の名前は空になります。

クラッシュの理由は、returngetLastWorkerに書き込むことを忘れたためです。
コンパイラの警告レベルを上げ、注意してください。

関連する問題