我更喜欢在任何地方都使用引用,但是当您使用 STL 容器时,您必须使用指针,除非您真的想按值传递复杂类型。
需要明确一点:STL 容器旨在支持某些语义(“值语义”),例如“容器中的项目可以被复制”。由于引用不可重新绑定,它们不支持值语义(即,尝试创建 std::vector<int&> 或 std::list<double&>)。您是正确的,您不能将引用放在 STL 容器中。
通常,如果您使用引用而不是普通对象,那么您要么使用基类并希望避免切片,要么试图避免复制。而且,是的,这意味着如果您想将项目存储在 STL 容器中,那么您将需要使用指针来避免切片和/或复制。
而且,是的,以下是合法的(尽管在这种情况下,不是很有用):
#include <iostream>
#include <vector>
// note signature, inside this function, i is an int&
// normally I would pass a const reference, but you can't add
// a "const* int" to a "std::vector<int*>"
void add_to_vector(std::vector<int*>& v, int& i)
{
v.push_back(&i);
}
int main()
{
int x = 5;
std::vector<int*> pointers_to_ints;
// x is passed by reference
// NOTE: this line could have simply been "pointers_to_ints.push_back(&x)"
// I simply wanted to demonstrate (in the body of add_to_vector) that
// taking the address of a reference returns the address of the object the
// reference refers to.
add_to_vector(pointers_to_ints, x);
// get the pointer to x out of the container
int* pointer_to_x = pointers_to_ints[0];
// dereference the pointer and initialize a reference with it
int& ref_to_x = *pointer_to_x;
// use the reference to change the original value (in this case, to change x)
ref_to_x = 42;
// show that x changed
std::cout << x << '\n';
}
哦,你不知道对象是否是动态创建的。
这不重要。在上面的示例中,x 在堆栈上,我们将指向x 的指针存储在pointers_to_vectors 中。当然,pointers_to_vectors 在内部使用动态分配的数组(当vector 超出范围时,delete[]s 该数组),但该数组包含指针,而不是指向的东西。当pointers_to_ints 超出范围时,内部int*[] 是delete[]-ed,但int*s 不是deleted。
事实上,这使得在 STL 容器中使用指针变得困难,因为 STL 容器不会管理指向对象的生命周期。您可能想查看 Boost 的指针容器库。否则,您将 (1) 想要使用智能指针的 STL 容器(例如 boost:shared_ptr,这对于 STL 容器是合法的)或 (2) 以其他方式管理指向对象的生命周期。您可能已经在做 (2)。