0

C++98 (古いもの) を使用します。

テーブルがあり、ルックアップを考えてみましょう。Ptr はスマート ポインターです。以下のステートメント 1. - .3 は正しいですか、それとも考慮されている両方のケースは、発信者の観点から同じように安全/安全ではありませんか?

検索の関数プロトタイプ:

const Y::Ptr & lookup(const X::Ptr & x);

そして、ルックアップが呼び出される呼び出し元関数:

const Y::Ptr & ret = lookup(x);

ここで、x は X::Ptr オブジェクトまたは X::Ptr の参照です。したがって、上記の 2 行に基づいて、次の使用法があります。

  1. 関数の引数const X::Ptr &。これは通常安全でありX::Ptr、関数呼び出しが行われたときのコピー コンストラクターを回避します。呼び出し元は、ルックアップ関数呼び出しの間X、オブジェクトの参照を保持する責任があります。X
  2. 戻り値const Y::Ptr &。これは安全ではありません。この参照がスタック上にある短い期間に、スレッドが中断または中断され、別のスレッドがテーブルからエントリを削除すると、Y オブジェクトとオブジェクトの両方Y::Ptrが削除されるためです。その結果、Y::Ptrスタック上の参照は、なくなった Ptr オブジェクトを参照します。
  3. const Y::Ptr &ルックアップの戻り値を格納するためのローカル参照。#2 と同様の理由で、これは安全ではありませんが、呼び出し元関数でのこのローカル参照のスコープが、戻り値としてのスタック上の参照よりも長いため、おそらくさらに悪いことです。
4

2 に答える 2

0

私はあなたがそれについて正しいと思います。明らかに、解決策はスマート ポインターを値で返すことです。ポイント#2は#3に完全に含まれているため、ポイント#2について具体的に考える必要はあまりないことに注意してください(使用しない、または使用できない参照を持つポイントがないため)。

于 2013-10-17T12:36:04.783 に答える
0

多くは、何lookupをするか、何を達成しようとしているのかによって異なります。論理的に値を返すか、内部データへの参照を返しますか? のような名前の関数lookupは後者の場合が多く、戻り値が参考になることが重要な場合が多いです。(明らかなケースは のような関数operator[]ですstd::vector。) ただし、セマンティクスで参照が必要でない限り、値で返す方が適切です。

呼び出しサイトでも同様です。呼び出し元がデータ構造への参照を必要とする場合、変数を参照として宣言する必要があります。それ以外の場合は、値であると宣言する必要があります。(もちろん、関数が値を返す場合、ローカル変数が参照であるべき合理的なケースはありません。)

ここでは、マルチスレッドはニシンだと思います。他のスレッドがデータ構造のlookup使用を変更している場合は、外部同期が必要です。関数が参照を返し、それを参照として保持する場合、クリティカル セクションには参照の有効期間が含まれますが、これは通常大きな問題ではありません。そうである場合、呼び出し元は結果を値として保存し、それを処理することができます。

原則として、C++ は値のセマンティクスを優先します。この言語は、コンパイラが不要なコピーを最適化できるようにする特別な規則を含め、これを念頭に置いて最適化されています。それと戦わないでください。唯一の例外は const、関数パラメーターの参照を使用することです。(しかし、ここでも一貫性を保つ必要があります。どこにでもある規則は、クラスの型を const への参照によって渡し、他の型を値によって渡すことです。これがコードで使用されているルールである場合は、例外なく体系的に使用してください。)

于 2013-10-17T13:22:58.670 に答える