Добавление пустого элемента в объявленный контейнер без объявления типа элемента

#c #c 11

#c #c 11 #c

Вопрос:

Когда мы используем сложный контейнер в C , например

 std::vector<std::map<std::string, std::set<std::string>>> table;
  

Единственный способ добавить пустую карту (которая может представлять строку или столбец) — это инициализировать новый элемент и вернуть его обратно. Например, с

 table.push_back(std::map<std::string, std::set<std::string>>());
  

Есть ли какой-нибудь способ избежать повторного объявления типа и просто добавить правильный типизированный элемент?

Ответ №1:

Позже я обнаружил, что из clion’s IntelliSense есть один полезный метод emplace_back() . Это создает новый объект правильного типа и добавляет его в конец вектора.

 table.emplace_back();
  

Ответ №2:

Вы можете воспользоваться copy-list-initialization (начиная с C 11) и просто написать

 table.push_back({});
  

Ответ №3:

До C 11 иногда я использовал x.resize(x.size() 1) , в C 11 или более поздней версии вы можете использовать x.push_back({}) .

Ответ №4:

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

Я могу, конечно, только догадываться о логическом значении ваших контейнеров, и это еще одна вещь, которую это исправляет!

  using PhilosopherNameType = std::string;
 using NeighboursType      = std::set<PhilosopherNameType>;
 using NeighbourMapType    = std::map<PhilosopherNameType, NeighboursType>;

 std::vector<NeighbourMapType> table;
 table.push_back(NeighbourMapType());
  

Я упоминаю об этом, потому что вы, вероятно, все еще можете извлечь выгоду из этого в других местах.

Комментарии:

1. согласовано. В тех же строках приведены типы, которые предоставляет вам STL (vector::value_type iirc)

2. Есть ли практическая разница между использованием «using …. = …» и typedef?