у меня есть std::vector<std::vector<double>>
и хотел бы добавить некоторые элементы в конце этого, так что это был мой пробный период:
std::vector<std::vector<double> > vec;
vec.emplace_back({0,0});
но это не компилируется, тогда как следующее будет делать:
std::vector<double> vector({0,0});
Почему emplace_back не может создать элемент в этой позиции? Или что я делаю не так?
Спасибо за вашу помощь.
Шаблонный вывод не может угадать, что заключенный в скобки список инициализации должен быть вектором. Вы должны быть явными:
vec.emplace_back(std::vector<double>{0.,0.});
В предыдущем ответе упоминалось, что вы можете получить код для компиляции, когда вы строите вектор в строке и используете его.
Это означает, однако, что вы вызываете конструктор перемещения для временного вектора, что означает, что вы не создаете вектор на месте, в этом и заключается вся причина использования emplace_back
скорее, чем push_back
,
Вместо этого вы должны привести список инициализатора к initializer_list
, вот так:
#include <vector>
#include <initializer_list>
int main()
{
std::vector<std::vector<int>> vec;
vec.emplace_back((std::initializer_list<int>){1,2});
}
std::vector<double>
конструктору разрешено использовать ограниченный список int
с его std::vector<double>(std::initializer_list<double>)
конструктор.
emplace_back()
не может создать элемент из выражения фигурных скобок, потому что это шаблон, который использует идеальную пересылку. Стандарт запрещает компилятор для вывода типа {0,0}
, так что std::vector<double>::emplace_back<std::initializer_list<double>>(std::initializer_list<double>)
не компилируется для emplace_back({})
,
Другой ответ указывает на то, что emplace_back
Можно быть скомпилированным для аргумента типа std::initializer_list<T>
если он не должен выводить тип непосредственно из {}
выражение. В качестве альтернативы приведению аргумента к emplace_back
Вы могли бы сначала построить аргумент. Как указано в пункте 30 Мейерса («Эффективный современный C ++»), auto
разрешено выводить тип выражения фигурной скобки, а совершенная пересылка позволяет выводить тип объекта, тип которого был выведен auto
,
std::vector<std::vector<double> > vec;
auto int_list = {0, 0}; // int_list is type std::initializer_list<int>
vec.emplace_back(int_list); // instantiates vec.emplace_back<std::initializer_list<int>>
emplace_back
добавляет элемент к vec
позвонив std::vector<double>(std::forward<std::initializer_list<int>>(int_list))
, который вызывает std::vector<double>(std::initializer_list<double>)
конструктор и элементы int_list
конвертированы.