Почему я не могу создать вектор ссылок?

Когда я это сделаю:

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]);
}