C ++ 11およびSTLコンテナーでのセマンティクスの移動

これは、 新しいC ++ 11標準の出現により、要素の標準コンテナの要件がどのように変化したかについての短いメモです。 C ++ 98では、実際には、「合理的な」コピーコンストラクターと代入演算子を持つためにコンテナー要素が必要でした。 たとえば、クラスのオブジェクトがリソースを所有している場合、コピーは通常不可能になります(少なくともリソースの「深い」コピーなしでは)。 例として、C ++ 98で記述されたFILE*



次のラッパークラスを見てみましょう。



 class File { FILE* handle; public: File(const char* filename) { if ( !(handle = fopen(filename, "r")) ) throw std::runtime_error("blah blah blah"); } ~File() { if (handle) fclose(handle); } // ... private: File(const File&); //  void operator=(const File&); //  };
      
      









FILE*



コピーにはプラットフォーム固有のトリックが必要であり、通常は物理的な意味があまりないため、このクラスのオブジェクトのコピーおよび割り当てを禁止します。



File



型のオブジェクトのリスト全体を保存する場合はどうしますか? 残念ながら、標準コンテナでFile



を使用することはできません。つまり、このようなコードは単にコンパイルされません。



 std::vector<File> files; files.push_back(File("data.txt"));
      
      







C ++ 98でのこの問題の一般的な解決策は、 shared_ptr



を使用することです。

 std::vector<boost::shared_ptr<File> > files; files.push_back(boost::shared_ptr<File>(new File("data.txt")) );
      
      







このソリューションは、特に必要ではないと思われる動的メモリを使用するという事実を考慮すると、目には特に喜ばしいものではありません。



C ++ 11の使用を許可すると、状況は大きく変わります。 移動セマンティクスの出現により、標準コンテナでは、コンテナ全体をコピーする場合を除き、通常のコピーコンストラクタと代入演算子は不要になりました。 代わりに、ディスプレイスメントのセマンティクスで十分です。 C ++ 11のFile



クラスを使用して例を書き換える方法を見てみましょう。



 class File { FILE* handle; public: File(const char* filename) { if ( !(handle = fopen(filename, "r")) ) throw std::runtime_error("blah blah blah"); } ~File() { if (handle) fclose(handle); } File(File&& that) { handle = that.handle; that.handle = nullptr; } File& operator=(File&& that) { std::swap(handle, that.handle); return *this; } File(const File&) = delete; //  void operator=(const File&) = delete; //  // ... };
      
      







繰り返しますが、通常のコピーは禁止しますが、オブジェクトの移動は許可します。 これでこのコードは機能します:



 std::vector<File> files; files.push_back(File("data1.txt")); files.push_back(File("data2.txt")); files.erase(files.begin());
      
      







さらに、可変テンプレートのおかげで、新しいテンプレート関数emplace_back



コンテナに登場しました。これにより、オブジェクトをコピーせずにコンテナ内に直接作成できます。



 std::vector<File> files; files.emplace_back("data1.txt"); //  File("data1.txt")   
      
      







このノートが、イノベーションが移動オブジェクトのセマンティクスであることの重要性を明確に示していることを願っています。 新しい標準への移行におけるすべての成功!



All Articles