如果我的某个类包含许多int
,float
和enum
成员变量,那么将它们作为引用而不是副本返回是一种有效和/或良好的做法,并返回常量引用,不应该进行任何更改?或者我有理由将它们作为副本归还吗?
答案 0 :(得分:7)
没有理由通过引用返回基本类型,例如int
和float
,除非您希望允许更改它们。通过引用返回它们实际上效率较低,因为它不会保存任何内容(int
和指针通常具有相同的大小),而解除引用实际上会增加开销。
答案 1 :(得分:4)
如果它们是常量引用,也许就可以了。如果它们不是常量引用,可能不是。
关于效率 - 在64位机器上,引用将是64位数量(伪装指针); int
和float
以及enum
会更小。如果您返回引用,则表示您正在强制间接;它的效率较低。
因此,特别是对于内置类型作为返回值,通常最好返回值而不是引用。
答案 2 :(得分:4)
有些情况是必要的:
查看任何课程的重载operator[]
。它通常有两个版本。变异版本必须返回引用。
int &operator[](int index); // by reference
int operator[](int index) const; // by value
一般情况下,允许某个类通过可信实体访问类成员是可以的。朋友。如果这些可信实体还需要修改状态,引用或指向类成员的指针,则是唯一的选项。
在许多情况下,引用通常会简化语法,例如'v'是STL向量。
v.at(1) = 2 vs *(v.at(1)) = 2;
答案 3 :(得分:1)
这可能主要是风格或偏好问题。不返回引用的一个原因是因为您使用getter和setter来允许您更改这些成员的实现,如果您将私有成员更改为其他类型,或者因为可以计算它而完全删除它,那么您不再拥有返回引用的能力,因为没有什么可引用的。
另一方面,返回非平凡类型(复合类)的引用可以使代码比复制更快一些,并且可以允许通过返回的引用(如果需要)分配这些成员。 / p>
答案 4 :(得分:0)
差不多,const引用更好。对于整数而言,这一点没有意义,因为你希望它们被改变,或者因为它们的大小(或几乎)与参考相同。
所以是的,这是一个好主意。我更喜欢另一种语言或者用我自己的C ++东西进行破解,只是让var公开(再一次只是我自己的东西)
答案 5 :(得分:0)
这是性能问题,但从稳健性的角度来看,我会说最好是返回值而不是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);
}
}
}
因此,如果它具有语义意义,我们可以避免过多的动态分配,我更喜欢按值返回。
答案 6 :(得分:0)
吸气剂是针对类Exhaust Car.emit()
的排放,其中汽车刚刚创建了Exhaust
。
如果您有义务写const Seat& Car.get_front_seat()
如果稍后坐在Driver
,您可以立即注意到有问题
老实说,你宁愿写Car.get_in_driver(Driver)
然后直接调用seat.sit_into(Driver)
。
第二种方法可以轻松避免当你get_front_seat
时出现尴尬的情况,但是门关闭了,而你几乎是通过关闭的门推动驾驶员。记住,你只要求一个座位! :)
总而言之:始终按价值返回(并依赖于返回值优化),或者意识到是时候改变您的设计了。
后台:创建了类,以便数据可以与其访问器功能耦合在一起,本地化错误等。因此,类从不是活动,而是面向数据。
进一步的陷阱:在c ++中如果你通过const ref返回一些东西,那么你很容易忘记它只是一个参考,一旦你的对象被破坏,你可能会留下一个无效的参考。否则,无论如何,该对象将在离开getter后被复制。但编译器可以避免使用不必要的副本,请参阅Return Value Optimization。