Почему контейнеры const могут содержать ссылку на const? - PullRequest
0 голосов
/ 26 февраля 2020

Как следует из тайла, в C ++ у нас не может быть содержимого, содержащего ссылки, поскольку объекты внутри контейнеров должны быть назначаемыми. Мы не можем переназначить ссылку после ее инициализации.

Тем не менее, в моей программе у меня есть static const std::map, который содержит константную ссылку в качестве значений и прекрасно компилируется. Мне интересно, если причина в том, что карта объявляется как const и инициализируется при объявлении, что говорит компилятору, что «этот объект является const, и его содержимое не изменится, поэтому можно использовать ссылку на const в качестве значений».

Я не мог найти ответы где-либо еще. Код работает, но я не хочу, чтобы он сбивал с толку других разработчиков.

Edit, Извините, я не включил код. Вот оно:

const glm::dvec4& GetObjectColor(const msg::ObjectType type) {
  static const std::map<msg::ObjectType, const glm::dvec4&> kObjectColorMap = {
      {msg::ObjectType::PERSON, kWhite},
      {msg::ObjectType::ANIMAL, kSilver},
      {msg::ObjectType::SEDAN, kGray},
      {msg::ObjectType::SUV, kRed},
      {msg::ObjectType::VAN, kMaroon},
      {msg::ObjectType::BICYCLE, kYellow},
      {msg::ObjectType::TRICYCLE, kOlive},
      {msg::ObjectType::MOTORCYCLE, kLime},
      {msg::ObjectType::TRUCK, kGreen},
      {msg::ObjectType::BUS, kAqua},
      {msg::ObjectType::PICKUP, kTeal},
      {msg::ObjectType::UNKNOWN, kBlue}};
  return kObjectColorMap.at(type);  
}

1 Ответ

0 голосов
/ 27 февраля 2020

Нет. Тебе нельзя.

Может быть, вы уже видели этот вопрос: Почему хранение ссылок (не указателей) в контейнерах в C ++ не работает?

Предпосылка вопроса правильна. Вы не можете хранить ссылки в контейнерах.

... и он прекрасно компилируется.

Код, не вызывающий ошибку компилятора, нельзя с уверенностью считать правильным. На самом деле «компиляция без ошибок» - это самая низкая полоса, которую вы можете поместить в код. Рассмотрим этот ужасно испорченный код:

int* dont_do_this_at_home;   
*dont_do_this_at_home = 42;   // serisouly: DONT DO THIS

Ни один из известных мне компиляторов не выдаст ошибку или предупреждение для этого кода, независимо от того, что этот код не может быть более взломан. Лучшее, что может случиться здесь, это то, что вы получаете ошибку сегментации. Худшее: демоны вылетают из твоего носа. Прочитайте здесь о неопределенном поведении: https://en.cppreference.com/w/cpp/language/ub

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

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

Учтите это:

int a = 5;
std::map<int,int&> x{ { 1,a} };   // WRONG !!!

Нет ошибки компилятора, но все же это не так. C ++ - это не футбол, если вы нарушаете правила, нет ни одного судьи, который бы вам об этом сказал.

PS: есть std::reference_wrapper для хранения ссылок в контейнерах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...