いつまでに帰ればいいT const&
ですか?オブジェクトを変更しない場合、値で返すのとどう違うのかわかりません。また、const 参照による戻りは、コピーが作成されないことを意味します。T const&
だからいつ有用で戻ってきます。
6 に答える
const&
値ではなく値で返すことを好む理由は 2 つあります。
1つ目はセマンティクスです。何かを返すコードconst&
は、呼び出し元に明示的に「これはあなたが要求したものの読み取り専用バージョンです。それを永続的に保存したり、変更したりしたい場合は、コピーを作成する責任があります。 " この戻り型のセマンティクスは非常に明確で、簡単に適用できます。
2 つ目は最適化です。値によって何かを返すことにより、コンパイラからいくつかの最適化の機会を取り除きます。これは、値による戻りが、値による戻りよりも効率が悪いと言っているわけではありません(実際、逆の場合もあります。64 ビット システムで aを返す関数を考えてみてください)。これは単に、コンパイラの最適化ツールボックスからツールの 1 つを削除することを意味します。それを置き換える別のツールがあります-つまり、呼び出しをインライン化してコピーを省略します-したがって、これは面倒かもしれません。それはすべて文脈に依存します。const&
char
「セマンティクス」が最も重要であると考えているため、最初の理由として「セマンティクス」について言及します。最適化には非常に多くの変数があり、非常に多くの可動部分があるため、コンパイラーがどの最適化をいつ採用できるかを知ることはしばしば困難です。ただし、常に確実なことは 1 つあります。明確なセマンティクスは、混乱したセマンティクスよりも人間が理解しやすいということです。
返される一般的なケースconst T&
は、const
getter メンバー関数です。
T& get() { return m_some_private_member; }
const T& get() const { return m_some_private_member; }
この場合、コピーを作成したくないことがよくあります。オブジェクトへの参照を返したいだけであり、const-correctness のためにconst
ゲッターも提供する必要がある場合があります。
十分に安定したオブジェクトがある場合。
単純なケースの 1 つは、コンテンツをそのように返すコレクションの場合です。ちょっと主な仕事の説明。
nonconst & 別の通常のケースでは、引数で取得したものを返すことです (非表示の this ポインターを含む)。これは const& にも同様に適用できますが、パラメーターが短時間で消える一時にバインドされている場合のリスクに注意してください。& を取得し、内容を変更した後に const& を返すと、よりうまく機能します。
データ メンバーへの参照を返すことはできますが、「内臓を漏らさない」というガイドラインに適合します。
いずれにせよ、ref を返す場合は、有効性についてクライアントに文書を提供する必要があります。その説明を考え始めると、そもそもそれが理にかなっているのかどうかがわかります。
もう 1 つの明白なケースは、コピーできない (または想定されている) ID オブジェクトです。主流の使用のために const& を返すアクセサと、書き込みアクセスを持つアクセサが必要なのは理にかなっています。
では、以下のように関数が誤用されるのを避けることができますか?
class A
{
int x;
public:
int show()
{
return x;
}
A(int a)
{
x = a;
}
A const& operator+(A& inp)
{
inp.x = this->x + inp.x;
return inp;
}
};
int main()
{
A a(1),b(2),c(0),d(420);
a + b = d;
std::cout<<b.show();
}
これにより、420
出力が得られます。オーバーロードは として使用されることになっていますがd = a + b
、返された参照が別のオブジェクトに割り当てられるのを止めるものは何もありません。
関数の戻り値の型を次のようにすると、A const&
返される参照は定数であり、他のオブジェクトを割り当てることはできません。したがって、演算子はas としてのみ使用し、 etcd = a + b
を許可しない必要があります。a + b = d
g++ はエラーerror: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers
を返し、そのような誤用を効果的に防ぎます。
特に複雑な型、またはコピー コンストラクターで多くの作業を行う型の場合は、コピーを作成しない方が効率的です。