Почему я не могу создать вектор ссылок?
Когда я это сделаю:
std::vector<int> hello;
Все отлично работает. Однако, когда я делаю вместо него вектор ссылок:
std::vector<int &> hello;
Я получаю ужасные ошибки, такие как "ошибка C2528:" указатель ": указатель на ссылку является незаконным".
Я хочу поместить кучу ссылок на структуры в вектор, так что мне не нужно вмешиваться в указатели. Почему вектор бросает истерику по этому поводу? Могу ли я использовать вектор указателей вместо этого?
Ответы
Ответ 1
Тип компонента контейнеров, такие как векторы должен быть назначаемым. Ссылки не назначаются (вы можете их инициализировать только один раз, когда они объявлены, и вы не можете заставить их ссылаться на что-то еще позже). Другие не назначаемые типы также не допускаются как компоненты контейнеров, например, vector<const int>
не допускается.
Ответ 2
да, вы можете искать std::reference_wrapper
, который имитирует ссылку, но может быть назначен, а также может быть "повторно установлен"
Ответ 3
По самой своей природе ссылки могут быть установлены только в момент их создания; т.е. следующие две линии имеют очень разные эффекты:
int & A = B; // makes A an alias for B
A = C; // assigns value of C to B.
Далее, это незаконно:
int & D; // must be set to a int variable.
Однако, когда вы создаете вектор, невозможно назначить значения элементам при создании. Вы, по сути, просто делаете целую кучу последнего примера.
Ответ 4
Ион Тодирель уже упомянул ответ ДА с помощью std::reference_wrapper
. С С++ 11 у нас есть механизм для извлечения объекта из std::vector
и удаления ссылки с помощью std::remove_reference
. Ниже приведен пример, скомпилированный с использованием g++
и clang
с параметром
-std=c++11
и успешно выполнен.
#include <iostream>
#include <vector>
#include<functional>
class MyClass {
public:
void func() {
std::cout << "I am func \n";
}
MyClass(int y) : x(y) {}
int getval()
{
return x;
}
private:
int x;
};
int main() {
std::vector<std::reference_wrapper<MyClass>> vec;
MyClass obj1(2);
MyClass obj2(3);
MyClass& obj_ref1 = std::ref(obj1);
MyClass& obj_ref2 = obj2;
vec.push_back(obj_ref1);
vec.push_back(obj_ref2);
for (auto obj3 : vec)
{
std::remove_reference<MyClass&>::type(obj3).func();
std::cout << std::remove_reference<MyClass&>::type(obj3).getval() << "\n";
}
}
Ответ 5
boost::ptr_vector<int>
будет работать.
Изменить: было предложено использовать std::vector< boost::ref<int> >
, который не будет работать, потому что вы не можете по умолчанию построить boost::ref
.
Ответ 6
Это ошибка на языке С++. Вы не можете взять адрес ссылки, так как попытка сделать это приведет к адресу адреса, на который ссылается, и, следовательно, вы никогда не сможете получить указатель на ссылку. std::vector
работает с указателями на его элементы, поэтому для хранения значений необходимо указывать. Вместо этого вам придется использовать указатели.
Ответ 7
Как уже упоминалось, вы, вероятно, в конечном итоге будете использовать вектор указателей.
Однако вам может потребоваться вместо этого использовать ptr_vector!
Ответ 8
Как показывают другие комментарии, вы ограничены использованием указателей.
Но если это помогает, вот один из способов избежать прямого обращения с указателями.
Вы можете сделать что-то вроде следующего:
vector<int*> iarray;
int default_item = 0; // for handling out-of-range exception
int& get_item_as_ref(unsigned int idx) {
// handling out-of-range exception
if(idx >= iarray.size())
return default_item;
return reinterpret_cast<int&>(*iarray[idx]);
}