クラッシュしなければならないが、この文では、塩の粒で撮影する必要がありません
ありません。 C++には "クラッシュする必要がある"という概念はありません。これには、定義されていない動作の概念があり、クラッシュする可能性があります。それでも、コードには未定義の動作はありません。
両方のインスタンスの
c_str年代が同じ場所を参照してください(この私が理解し、 コンストラクタはビットごとにコピーされ、文字列は内部的に のchar *のデータを格納し、ポインタがコピーされてしまったコピー。
あなたは実装std::string
のについて話している。あなたが代わりに安全であるとされていないどの操作を決定するために、そのインターフェースを見なければならない必要があります。
これ以外にも、コピーオンライトや「COW」と呼ばれる実装についてはis obsolete since C++11です。最新のGCCのバージョンはそれを放棄しました。
はGCC 5 Changes, New Features, and Fixesを参照してください:
std::string
の新しい実装が代わりにコピー・オン・ライト参照カウントの 小さな文字列の最適化を使用して、デフォルトで有効になっています。
小文字の最適化は、たとえばVisual C++実装のstd::string
でも使用されているのと同じ手法です。これは完全に異なる方法で動作しますので、十分に新しいGCCバージョンを使用するか、Visual C++を使用すると正しいことがない場合、std::string
が内部でどのように動作するかについてのあなたの理解は、もはや正しくありません。
しかし、このコードがクラッシュしないのはなぜですか?
std::string
の操作はインターフェイスのドキュメントに従って正しく使用されているため、またコンパイラが完全に壊れていないためです。
基本的に、コンパイラが正しいコードのために動作するバイナリを作成する理由を尋ねています。
A1とA2がスタックされた変数、
はい(正しい用語は、オブジェクトが "自動記憶域期間" を持っていることであろう)。
文字列Bを分解すると、その文字列の内部char *(同じメモリ位置を指す)が2回削除されますか?
コンパイラのstd::string
実装では、このようなことは起こりません。 COWをまったく使用しないか、デストラクタに共有バッファがすでに削除されているかどうかをチェックするコードが含まれています。
古いGCCバージョンを使用している場合は、std::string
実装のソースコードを見れば、それがどのように実行されたかを知ることができます。結局のところ、オープンソースだが、恐ろしく見えるかもしれないので注意する。例えば、ここにan older GCC versionのデストラクタコードだ:
~basic_string()
{ _M_rep()->_M_dispose(this->get_allocator()); }
その後(同じファイルに)_M_dispose
を見て、あなたはそれがさまざまなチェックとsynchronisationsと非常に複雑な実装だとわかります。
std::string
をコピーするの膨大な行為がクラッシュにつながる場合には、クラス全体が完全に無意味だろう、それはないだろう:
はまた、この検討してください?
C++で「クラッシュすべき」と考えるのはほとんど常に間違っています。しかし、この場合、コードが持つと思う問題は文字列クラスによって処理されます。 – chris