何时使用引用
When do I use references?
我对引用的理解是它们是已经存在的变量的别名 - 它们不能为空。它们对于修改原始输入时的函数调用很有用,因为引用被认为比指针更安全。
除了上述情况以及引用是强制性的情况之外,是否有其他原因/用例使用引用而不是引用指向的已经存在的变量?
编辑:请注意,除了上述内容之外,我说的还有。这意味着我想知道在调用函数之外,什么时候其他引用有用 - 当不需要时(我已经知道了(。我还特别想知道何时引用优先于原始变量,而不是指针(我已经从另一个问题中学到了"尽可能使用引用,必须使用指针"在两者之间进行选择时
假设你有一个大结构,或者一个std::vector
或一个std::string
对象,你通过值将其传递给函数。这意味着对象被复制,这对于大型对象(例如数百万个条目的向量(可能非常低效。然后,您可以使用对常量对象的引用,例如 std::vector<SomeType> const& my_object
.
我们使用引用是因为以下事情
修改调用方函数的局部变量。
用于传递大型参数。
以避免对象切片。
在函数中实现运行时多态性。
有关详细信息,请参阅 http://www.geeksforgeeks.org/when-do-we-pass-arguments-by-reference-or-pointer/
尽可能使用引用而不是指针。除非你想操纵低级内存,否则你不应该处理指针。另一种用法是使用 new 作为指针将主要数据保留在堆上,并传递该指针的引用。但是,对于新的unique_ptr,shared_ptr和weak_ptr的组合甚至不需要。唯一需要指针的地方是对象可以是 nullptr 时,因为引用不能为 NULL。您可以放心地假定引用是有效的对象,除非有人以不正当的方式扭曲了代码。
常见的误解是引用比指针更安全,但这是一个误解。生成空引用和其他非法引用同样容易。这些可以在炸毁程序之前传播很远。以下是一些示例:
- 创建空引用
:只需取消引用空指针即可将结果传递给需要引用的内容。
class Foo { public: Foo() : bar(null_ptr) {} void setSize(size_t newSize) { delete bar; bar = new int[newSize]; } doSomething() { myVec.push_back(bar[0]); //This will blow up somewhere in the push_back() implementation, not here! } private: int* bar; std::vector<int> myVec; }; void baz() { Foo myFoo; myFoo.doSomething(); }
关键是上面的代码不会在你取消引用空指针时爆炸,它只会静默地创建一个空引用。这是合法的,因为取消引用空指针被定义为未定义的行为,而创建空引用是编译器可以执行的有效操作。
空引用将被成功传递给
std::vector<>::push_back()
,只有当它本身试图使用引用来实际获取它后面的值时,才会出现段错误。悬空引用:只需让引用的对象在引用结束其生存期之前结束即可。同样,与指针相同的问题:
std::vector<int> foo; foo->push_back(7); int& bar = foo[0]; //perfectly legal bar *= 6; //perfectly legal foo->push_back(8); //perfectly legal cout << "The answer is: " << bar; //BOOM, bar is dangling, undefined behavior results
注意:此代码实际上可能按预期运行,就像访问悬空指针的代码可以按预期重现运行一样。
超出范围的引用:就像使用指针一样容易完成:
std::vector<int> array; array.resize(7); int& bar = array[7]; //undefined behavior, even if the compiler detects this, it will silently ignore it bar = 42; //since this is undefined behavior, the compiler may optimize away this line
与悬空引用一样,此代码可能运行良好,但它可能无法执行您认为的功能。由于优化,它甚至可能不会写入超出范围的元素。或者,它可能会损坏堆和/或堆栈,或者静默计算错误的结果。只是用段错误炸毁实际上是这里最不可能的结果。
如您所见,最后两个示例代码甚至不需要任何地方的显式指针,它们仅使用现代、闪亮C++样式的数据结构。然而,它们会导致未定义的行为,这些行为不会在调用它的地方发生。非法引用可能会在明显的坏事开始发生之前从创建它的位置传播到任何距离。这正是人们害怕使用指针的原因;指针和引用的危险是相同的。
所以,真的,在对你有意义的地方使用引用。但不要依赖它们是"安全的"。
- 何时在引用或唯一指针上使用移动语义
- 何时应通过引用传递矢量参数而不是按值传递矢量参数?
- 如果非动态变量被指针引用,何时超出范围?
- 为什么通过 vector<reference_wrapper> 的元素删除引用的值<T>不会使向量无效?
- 何时使函数成为类成员函数C++?
- 何时使用右值引用
- 如何在 Linux 中构建共享库时使未定义引用的链接器失败
- C++ 何时使用常量引用而不是转发引用
- 了解shared_ptr传入函数时引用计数何时递增
- C++ / Qt:如何检测主机名或IP地址何时引用当前系统?
- 常量引用函数参数的地址何时唯一?
- C++ 传递对数组的引用以使其发挥作用
- 我可以更改将引用参数传递到指针中并使其正常工作的函数的输入(C、C++)吗?
- 何时必须使操作员<<过载?
- 当它们不与GCC和CMAKE一起使用时,如何解析未定义的引用
- 如果函数的返回值将用作右值引用而不是左值,有没有办法使函数具有不同的行为?
- 返回的常量引用究竟何时被销毁
- 何时引用为右值引用
- 为什么通过引用传递从 std::function 派生的对象会使程序崩溃?
- 何时应存储指向函数的引用或指针?