26

アプリの複数の場所で使用する文字列用の文字列定数があります。

namespace Common{
    static const std::string mystring = "IamAwesum";
}

別の質問 (コンパイル中にターゲットに含まれていない .h ファイルはどうなりますか? )について質問を投稿すると、別のユーザーが次のコメントを作成しました。

この場合、静的文字列はグローバルであることに注意してください。したがって、それらはいつでも例外を作成する可能性があり、キャッチすることはできません。文字列の参照を返す関数を使用することをお勧めします。std::string const &mystring { static std::string const mystring = "IamAwesum"; このようにして、オブジェクトは必要なときにのみ構築されます

上記の方法で static const 文字列を使用すると、例外がスローされるリスクがある理由を誰かが説明できますか?

4

3 に答える 3

5

唯一の「問題」-それを呼び出すことができれば-あなたのコードで見られるのは、すでに定数であるデータを動的に割り当てられたバッファーに不必要にコピーすることで無駄になっていることです(これは正式には定数ですが、実際にはそうではありません) )。これにより、必要な物理メモリの 2 倍が使用され、不要なコピーが行われます。

それは問題ですか?ほぼ間違いなく、いいえ。「かなり制限されたメモリ」システムでさえ、実行時間の観点からもメモリ消費の観点からも、これは最近ではほとんど目立ちません。

例外に関しては、もちろん技術的には、行わなければならない割り当てが失敗std::stringする可能性があるため、コンストラクタースローする可能性があり、それをキャッチすることはできません。しかし、現実的にしてください。
これが起こらないことはほぼ保証されていますが、たとえそうなったとしても...プログラムの起動中にいくつかの文字列にメモリを割り当てるのと同じくらい些細なことで失敗した場合、まったく異なるスケールで本当に深刻な問題が発生します!
その上、上記の別の回答に対するコメントで指摘されているように、これが起こると仮定すると、あなたはそれについて何をするつもりですか? プログラムはまったく実行できないので、実行できると思われるプログラムを強制終了することに他なりません。

現在、C++17 はそれほど遠くなく、string_viewすでにstd::experimentalいくつかの主流のコンパイラで利用できるようになっているため、別の方法を試すことができます:正しいものを使用してください

は、string_viewとは逆に、string非定数メモリを割り当てず、定数データをそこにコピーしてから、定数であると見なします。代わりに、定数データへのポインターを直接管理します。それだけです。
そうすれば、定数は真に (形式的にだけでなく) 定数であり、割り当ても例外の可能性もなく、二重のメモリ使用もありません。そして、ほとんどの場合、見た目も匂いもstring. 唯一の注目すべき違いは、 astring_viewが nul 終了を保証しないこと (ただし、それが指す文字定数は保証するため、これは無関係です) と、実際に定数であり、変更可能ではないという事実です...これはまさにあなたが望むものです。

于 2016-11-02T13:59:41.033 に答える
4

PDFドキュメントは、主に、静的または動的にリンクされたライブラリを使用したオブジェクトctorおよび初期化順序の大失敗からの例外を参照しています。

例外のコードで見られる唯一の危険は、 std::string の ctor が呼び出されたときにスローされる場合です。

本当に安全を確保したい場合は、C++ ctor を呼び出さない static const char* mystring を代わりに使用できます。

コードが共有ライブラリにあり、プロセスのアドレス空間に配置する必要があるという問題もあります。複雑な ctors (スローできる ctors) を使用しない場合、それは大きな問題ではないと思います。

于 2016-11-02T10:37:31.380 に答える