Подтвердить что ты не робот

Почему я не могу хранить ссылки на STL-карте в С++?

Я недооцениваю, что ссылки не являются указателями, а псевдонимами для объекта. Тем не менее, я до сих пор не понимаю, что именно это означает для меня как программиста, т.е. Что такое ссылки под капотом?

Я думаю, что лучший способ понять это - понять, почему я не могу хранить ссылку на карте.

Я знаю, что мне нужно перестать думать о ссылках как синтаксический грузинг по указателям, просто не уверен, как:/

4b9b3361

Ответ 1

Как я понимаю, ссылки реализуются как указатели под капотом. Причина, по которой вы не можете хранить их на карте, является чисто семантической; вам нужно инициализировать ссылку, когда она создана, и вы больше не сможете ее изменить. Это не связано с тем, как работает карта.

Ответ 2

Вы должны думать о ссылке как "указатель const к неконстантному объекту":

MyObject& ~~ MyObject * const

Кроме того, ссылка может быть построена только как псевдоним того, что существует (что необязательно для указателя, хотя и целесообразно, кроме NULL). Это не гарантирует, что объект будет оставаться вокруг (и действительно, у вас может быть ядро ​​при доступе к объекту через ссылку, если его больше нет), рассмотрите этот код:

// Falsifying a reference
MyObject& firstProblem = *((MyObject*)0);
firstProblem.do(); // undefined behavior

// Referencing something that exists no more
MyObject* anObject = new MyObject;
MyObject& secondProblem = *anObject;
delete anObject;
secondProblem.do(); // undefined behavior

Теперь для контейнера STL существует два требования:

  • T должен быть конструктивным по умолчанию (ссылка не указана)
  • T должен быть назначен (вы не можете reset ссылку, хотя вы можете назначить ее рефери)

Итак, в контейнерах STL вам нужно использовать прокси или указатели.

Теперь использование указателей может оказаться проблематичным для обработки памяти, поэтому вам может потребоваться:

НЕ используйте auto_ptr, возникает проблема с назначением, так как он изменяет правый операнд.

Надеюсь, это поможет:)

Ответ 3

Важное отличие от синтаксического сахара заключается в том, что ссылки не могут быть изменены, чтобы ссылаться на другой объект, чем тот, с которым они были инициализированы. Вот почему они не могут храниться на картах или в других контейнерах, потому что контейнеры должны иметь возможность изменять тип элемента, который они содержат.

В качестве иллюстрации этого:

A anObject, anotherObject;
A *pointerToA=&anObject;
A &referenceToA=anObject;

// We can change pointerToA so that it points to a different object
pointerToA=&anotherObject;

// But it is not possible to change what referenceToA points to.
// The following code might look as if it does this... but in fact,
// it assigns anotherObject to whatever referenceToA is referring to.
referenceToA=anotherObject;
// Has the same effect as
// anObject=anotherObject;

Ответ 4

Контейнер, в котором хранится ссылка , имеет, чтобы инициализировать все свои элементы при построении и, следовательно, менее полезен.

struct container
{
   string& s_;           // string reference
};

int main()
{
   string s { "hello" };
   //container {};       // error - object has an uninitialized reference member
   container c { s };    // Ok
   c.s_ = "bye";
   cout << s;            // prints bye
}

Кроме того, после инициализации хранение элементов контейнера не может быть изменено. s_ будет всегда ссылаться на хранилище s выше.

Ответ 5

на самом деле вы можете использовать ссылки на карте. я не рекомендую это для больших проектов, так как это может вызвать странные ошибки компиляции, но:

    map<int, int&> no_prob;
    int refered = 666;
    no_prob.insert(std::pair<int, int&>(0, refered)); // works
    no_prob[5] = 777; //wont compile!!! 
    //builds default for 5 then assings which is a problem
    std::cout << no_prob[0] << std::endl; //still a problem
    std::cout << no_prob.at(0) << std::endl; //works!!

поэтому вы можете использовать карту, но будет сложно гарантировать, что она будет использоваться правильно, но я использовал ее для небольших кодов (обычно конкурентоспособных).