int
、、float
およびメンバー変数が多数あるクラスがある場合enum
、それらをコピーではなく参照として返し、変更を加えてはならない場所で定数参照を返すことは効率的および/または良い習慣と見なされますか?それとも、コピーとして返却する必要がある理由はありますか?
7 に答える
変更を許可したい場合を除いて、参照int
などのプリミティブ型を返す理由はありません。参照によってそれらを返すことは、実際には何も節約しないため( sとポインターは通常同じサイズです)、逆参照は実際にオーバーヘッドを追加するfloat
ため、効率が低下します。int
それらが定数参照である場合、多分それはOKです。それらが定数参照でない場合は、おそらくそうではありません。
効率に関しては、64ビットマシンでは、参照は64ビット量(偽装のポインター)になります。int
そしてfloat
、enum
より小さくなります。参照を返す場合は、あるレベルの間接参照を強制していることになります。効率が悪くなります。
したがって、特に戻り値としての組み込み型の場合、一般に、参照よりも値を返す方が適切です。
必要な場合:
operator[]
任意のクラスのオーバーロードを見てください。通常、2つのバージョンがあります。変更バージョンは参照を返す必要があります。
int &operator[](int index); // by reference
int operator[](int index) const; // by value
一般に、クラスの信頼できるエンティティ(友人など)によるクラスメンバーへのアクセスを許可することは問題ありません。これらの信頼できるエンティティも状態を変更する必要がある場合は、クラスメンバーへの参照またはポインタが唯一のオプションです。
多くの場合、参照は通常構文を単純化します。たとえば、「v」はSTLベクトルです。
v.at(1) = 2 vs *(v.at(1)) = 2;
これはおそらくほとんどスタイルや好みの問題です。参照を返さない理由の1つは、getterとsetterを使用して、これらのメンバーの実装を変更できるようにするためです。プライベートメンバーを別のタイプに変更した場合、または計算できるために完全に削除した場合は、参照するものがないため、参照を返す機能。
一方、重要な型(複合クラス)の参照を返すと、コピーを作成するよりもコードの速度が少し速くなり、返された参照を介してそれらのメンバーを割り当てることができます(必要な場合)。
ほとんどの場合、const参照の方が優れています。intなどの場合、変更する必要があるため、または参照と同じサイズ(またはほぼ)であるため、意味がありません。
そうです、それは良い考えです。私は別の言語を好むか、自分のC ++のものをハックして、変数を公開できるようにします(もう一度、自分のものだけにします)
これは主にパフォーマンスの質問ですが、堅牢性の観点からは、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)
。
get_front_seat
この2番目の方法は、ドアが閉まっていて、ドアを閉めた状態でドライバーを事実上押し込むという厄介な状況を簡単に回避できます。覚えておいてください、あなたは席を要求しただけです!:)
全体として、 常に値で返す(そして戻り値の最適化に依存する)か、設計を変更する時期であることに気づきます。
背景:クラスは、データをアクセサ機能と組み合わせたり、バグをローカライズしたりできるように作成されました。したがって、クラスはアクティビティではなく、データ指向です。
さらなる落とし穴: C ++では、const refで何かを返すと、それがrefだけであることを簡単に忘れてしまい、オブジェクトが破棄されると、無効なrefが残る可能性があります。それ以外の場合、そのオブジェクトは、とにかくゲッターを離れるとコピーされます。ただし、コンパイラは不要なコピーを回避します。戻り値の最適化を参照してください。