如果我有一个包含许多
int
、float
和 enum
数据成员的类,将它们作为引用而不是副本返回,并返回不应更改的常量引用是否被认为是有效和/或良好的做法是制作出来的,还是有理由我应该将它们作为副本退回?
没有理由通过引用返回诸如
int
和 float
之类的基本类型,除非您希望允许更改它们。通过引用返回它们实际上效率较低,因为它不会节省任何内容(int
和指针通常大小相同),而取消引用实际上会增加开销。
如果它们是持续引用,也许就可以了。如果它们不是持续引用,可能不会。
关于效率 - 在 64 位机器上,引用将是 64 位数量(变相的指针);
int
和 float
和 enum
会更小。如果你返回一个引用,你就强制了一定程度的间接;效率较低。
因此,特别是对于作为返回值的内置类型,通常最好返回值而不是引用。
有些情况是必要的:
查看任何类的重载
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;
这可能主要是风格或偏好的问题。不返回引用的一个原因是因为您正在使用 getter 和 setter 来允许您更改这些成员的实现,如果您将私有成员更改为另一种类型,或者因为可以计算而将其完全删除,那么您不再拥有返回引用的能力,因为没有什么可以引用的。
另一方面,返回非平凡类型(复合类)的引用可以比制作副本稍微加快代码速度,并且您可以允许通过返回的引用分配这些成员(如果需要)。
几乎,const 引用更好。对于整数之类的没有意义,因为您希望更改它们或者因为它们与参考的大小相同(或接近)。
所以,是的,这是一个好主意。我更喜欢另一种语言,或者破解我自己的 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)
。
第二种方法可以轻松避免当您
get_front_seat
但门已关闭并且您几乎将驾驶员推入关闭的门时的尴尬情况。请记住,您只是要求一个座位! :)
总而言之:始终按值返回(并依赖于返回值优化),或者意识到是时候改变你的设计了。
背景:类的创建是为了将数据与其访问器功能耦合在一起,定位错误等。因此,类从来不是活动的,而是面向数据的。
进一步的陷阱:在c++中,如果你通过const ref返回一些东西,那么你很容易忘记它只是一个引用,一旦你的对象被破坏,你可能会留下一个无效的引用。否则,一旦该对象离开 getter,它就会被复制。但编译器会避免不必要的复制,请参阅返回值优化。