メンバー変数ゲッターの参照を常に返すことは良い考えですか?
-
04-10-2019 - |
質問
たくさんあるクラスがある場合 int
, float
, 、 と enum
メンバー変数、コピーではなく参照としてそれらを返すことは効率的および/または優れた慣行と考えられており、変更を行う必要がない場合に一定の参照を返すことができますか?それとも、コピーとしてそれらを返す必要がある理由はありますか?
解決
次のような原始的なタイプを返す理由はありません int
と float
参考までに、それらを変更することを許可したい場合を除きます。参照によってそれらを返すことは、実際には何も節約できないため、効率が低下します(int
sとポインターは通常同じサイズです)一方、繰り返しは実際に頭上に追加されます。
他のヒント
それらが一定の参照である場合、それは大丈夫かもしれません。それらが一定の参照でない場合、おそらくそうではありません。
効率について - 64ビットマシンでは、参照は64ビット量(変装のポインター)になります。 int
と float
と enum
小さくなります。参照を返すと、間接のレベルを強制しています。効率が低くなります。
したがって、特に戻り値として組み込まれたタイプの場合、一般に、参照よりも値を返す方が良いです。
いくつかのケースが必要です:
過負荷を見てください operator[]
任意のクラスの場合。通常、2つのバージョンがあります。変異バージョンは参照を返す必要があります。
int &operator[](int index); // by reference
int operator[](int index) const; // by value
一般に、クラスEGの信頼できるエンティティによってクラスメンバーへのアクセスを許可しても構いません。これらの信頼できるエンティティも州を変更する必要がある場合、クラスメンバーへの参照またはポインターが唯一のオプションです。
多くの場合、参照は通常、「V」がSTLベクトルである場合、構文を簡素化します。
v.at(1) = 2 vs *(v.at(1)) = 2;
これはおそらくスタイルや好みの問題です。参照を返さない理由の1つは、ゲッターとセッターを使用してそれらのメンバーの実装を変更できるため、プライベートメンバーを別のタイプに変更した場合、または計算できるために完全に削除したためです。参照するものは何もないので、参照を返す機能。
一方、非自明のタイプ(複合クラス)の参照を返すことは、コピーを作成することでコードを少しスピードアップでき、それらのメンバーに返された参照を通じて割り当てられるようにすることができます(必要に応じて)。
ほとんど、const参照の方が優れています。 INTなどの場合、ポイントはありません。なぜなら、それらを変更することを望んでいるか、参照と同じサイズ(またはほぼ)であるためです。
はい、それは良い考えです。私は別の言語を好むか、自分のc ++のものをハックして、varを公開するだけです(もう一度自分のものだけです)
これは主にパフォーマンスの質問ですが、堅牢性の観点からは、const参照の代わりに値を返すことができればいいと思います。その理由は、const参照でさえカプセル化を弱めるためです。このことを考慮:
struct SomeClass
{
std::vector<int> const & SomeInts () const;
void AddAnInt (int i); // Adds an integer to the vector of ints.
private:
std::vector<int> m_someInts;
};
bool ShouldIAddThisInt(int i);
void F (SomeClass & sc)
{
auto someInts = sc.SomeInts ();
auto end = someInts.end ();
for (auto iter = someInts.begin (); iter != end; ++iter)
{
if (ShouldIAddThisInt(*iter))
{
// oops invalidates the iterators
sc.AddAnInt (*iter);
}
}
}
したがって、それが意味的に理にかなっていて、私たちが価値で返すことを好む過度の動的な割り当てを避けることができる場合に備えて。
ゲッターは、クラスの排出のためです Exhaust Car.emit()
, 、車が作成したばかりです Exhaust
.
あなたが書くべきであるならば const Seat& Car.get_front_seat()
後で座ること Driver
, 、すぐに何かがおかしいことに気付くことができます。
コレクリー、あなたはむしろ書きたいです Car.get_in_driver(Driver)
その後、直接呼び出します seat.sit_into(Driver)
.
この2番目の方法は、あなたがそれらの厄介な状況を簡単に回避します get_front_seat
しかし、ドアは閉じられており、閉じたドアを通して運転手を事実上押し込みます。覚えておいてください、あなたは席を求めただけです! :)
概して: 常に価値で返されます (そして、返品価値の最適化に依存しています)、またはデザインを変更する時が来たことを認識してください。
背景:クラスは、データをアクセター機能、バグのローカルなどと結合できるように作成されました。したがって、クラスはアクティビティではなく、データ指向です。
さらなる落とし穴: c ++では、const refで何かを返す場合、それはrefのみであることを簡単に忘れることができ、オブジェクトが破壊されると無効なrefを残すことができます。それ以外の場合、そのオブジェクト コピーされます とにかくゲッターを離れたら。ただし、コンパイラによって不必要なコピーが回避されます。 返品値の最適化.