Я бы предпочел использовать ссылки везде, но как только вы используете контейнер 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
использует динамически распределяемый массив внутри (и delete[]
s, который массив, когда vector
выходит из области видимости), но этот массив содержит указатели, а не наведенные объекты.Когда pointers_to_ints
выпадает из области видимости, внутренний int*[]
является delete[]
-ed, но int*
s не delete
d.
Это, фактически, делает использование указателей с STLКонтейнеры жесткие, потому что контейнеры STL не будут управлять временем жизни указанных объектов.Возможно, вы захотите взглянуть на библиотеку контейнеров указателей Boost.В противном случае вы либо (1) захотите использовать контейнеры с интеллектуальными указателями STL (например, boost:shared_ptr
, что допустимо для контейнеров STL), либо (2) иным образом управлять временем жизни указанных объектов.Возможно, вы уже делаете (2).