1

私はこれについて明確な答えを与えるスレッドを見つけることができませんでした -

たとえば、コンストラクターがあります。

FanBookPost::FanBookPost(Fan* owner, std::string content);

ファンは私のコードの別のクラスですが、コンテンツは問題のあるものです:

std::string はポインターではないため、(fan, nullptr) を使用してコンストラクターを呼び出すことはできないと予想されます。ただし、コンパイルされます。...実行時にEXC_BAD_ACCESSでクラッシュします。

これは避けられますか?

4

4 に答える 4

3

あなたが観察しているのは、関数に渡されるstd::string文字ポインター (この場合) から暗黙的に作成できることです。nullptrただしstring、null ポインターから を作成することはできません。std::stringメソッドの署名に問題はありません。コンストラクターの契約に違反するクライアントの使用だけです。

于 2014-01-21T21:23:16.033 に答える
1

問題は、唯一の (必須の) パラメータとしてstd::stringa を取る非明示的な ctor があることです。これにより、 からへchar *の暗黙的な変換が行われますが、未定義の動作が発生します。これは、ctor が特に null 以外のポインターを必要とするためです。nullptrstd::string

これを防ぐにはいくつかの方法があります。おそらく最も効果的なのは、 (非定数) への参照を取得するstd::stringことです。これには、 (非一時的)stringをパラメーターとして渡す必要があります。

FanBookPost::FanBookPost(Fan* owner, std::string &content);

これは、渡された文字列を変更する機能を関数に与えるという不幸な副作用があります。また、(準拠するコンパイラ1では)nullptr または文字列リテラルを関数に渡すことができないことも意味します。実際の のインスタンスを渡す必要がありますstd::string

文字列リテラルを渡すことができるようにする場合は、char const *パラメーターを受け取るオーバーロードを追加できます。また、場合によってはパラメーターも受け取るオーバーロードも追加できnullptr_tます。前者は、文字列を作成して文字列への参照を受け取る関数を呼び出す前に、null 以外のポインターをチェックし、後者は、エラーをログに記録して無条件にプログラムを強制終了する (または、おそらくエラーをログに記録する) ようなことを行います。例外をスローします)。

面倒で不便ですが、現状よりはマシかもしれません。


  1. 残念ながら、MS VC++ がこの点で準拠していないことに最後に気付いたときです。非 const 参照によって一時オブジェクトを渡すことができます。通常、これはかなり無害です (一時的なものを変更できるようにするだけですが、通常は目に見える副作用はありません)。ただし、この場合、一時オブジェクトの受け渡しを防ぐために特に依存しているため、はるかに面倒です。
于 2014-01-21T21:38:14.967 に答える