Когда я делаю это:
std::vector<int> hello;
Все отлично работает. Однако, когда я делаю это вектор ссылок вместо этого:
std::vector<int &> hello;
Я получаю ужасные ошибки, такие как
ошибка C2528: указатель: указатель на ссылку недопустим
Я хочу поместить несколько ссылок на структуры в вектор, чтобы мне не приходилось вмешиваться в указатели. Почему вектор вызывает истерику по этому поводу? Является ли мой единственный вариант использовать вместо него вектор указателей?
Ответы:
Тип компонента контейнеров, таких как векторы, должен быть назначаемым . Ссылки не могут быть назначены (вы можете инициализировать их только один раз, когда они объявлены, и вы не можете заставить их ссылаться на что-то другое позже). Другие не присваиваемые типы также не допускаются в качестве компонентов контейнеров, например
vector<const int>
, не допускаются.источник
да, вы можете искать
std::reference_wrapper
, имитирующий ссылку, но назначаемый, а также можно «перезаписать»источник
get()
первым при попытке доступа к методу экземпляра класса в этой оболочке? Напримерreference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();
, не очень ссылка, как..get()
. Что timdiels хочетoperator.
; взгляните на последние предложения / обсуждения по этому вопросу.По своей природе ссылки могут быть установлены только во время их создания; то есть следующие две строки имеют очень разные эффекты:
Кроме того, это незаконно:
Однако, когда вы создаете вектор, нет способа присвоить значения его элементам при создании. По сути, вы просто делаете целую кучу последнего примера.
источник
Ион Тодирель уже упоминал ответ ДА, используя
std::reference_wrapper
. Начиная с C ++ 11 у нас есть механизм для извлечения объектаstd::vector
и удаления ссылки с помощьюstd::remove_reference
. Ниже приведен пример, скомпилированный с использованиемg++
иclang
с опцией-std=c++11
и успешно выполненный.источник
std::remove_reference<>
здесь. Смысл вstd::remove_reference<>
том, чтобы позволить вам написать «тип T, но без ссылки, если он один». Такstd::remove_reference<MyClass&>::type
же, как писатьMyClass
.for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n";
(или,for (const MyClass& obj3: vec)
если вы объявитеgetval()
const, как вы должны).boost::ptr_vector<int>
будет работать.Редактировать: было предложено использовать
std::vector< boost::ref<int> >
, которое не будет работать, потому что вы не можете создать по умолчанию aboost::ref
.источник
resize
.Это недостаток языка C ++. Вы не можете взять адрес ссылки, так как попытка сделать это приведет к адресу объекта, на который ссылаются, и, таким образом, вы никогда не сможете получить указатель на ссылку.
std::vector
работает с указателями на его элементы, поэтому на хранимые значения нужно указывать. Вы должны будете использовать указатели вместо этого.источник
sizeof
ссылку тоже.TL; DR
Используйте
std::reference_wrapper
как это:Demo
Длинный ответ
Как предполагает стандарт , для стандартного контейнера,
X
содержащего объекты типаT
,T
должен бытьErasable
отX
.Erasable
означает, что следующее выражение правильно сформировано:A
является типом распределителя контейнера,m
является экземпляром распределителя иp
является указателем типа*T
. Смотрите здесь дляErasable
определения.По умолчанию
std::allocator<T>
используется как распределитель вектора. При использовании распределителя по умолчанию требование эквивалентно действительностиp->~T()
(обратите внимание, чтоT
это ссылочный тип иp
указатель на ссылку). Однако указатель на ссылку недопустим , поэтому выражение сформировано некорректно .источник
Как уже упоминалось, вы, вероятно, в конечном итоге будете использовать вектор указателей.
Тем не менее, вы можете использовать ptr_vector !
источник
Как показывают другие комментарии, вы ограничены использованием указателей. Но если это помогает, вот одна из техник, чтобы избежать прямого столкновения с указателями.
Вы можете сделать что-то вроде следующего:
источник
reinterpret_cast
не нужен