У меня есть анимация, которая печатает в конструкторе по умолчанию деструктор и в другом конструкторе некоторые отличительные строки:
class Animation{
public:
int x;
Animation(int x) {
std::cout << "+ animation\n";
}
Animation() {
std::cout << "+ animation\n";
}
~Animation() {
std::cout << "- animation\n";
}
}
Я хочу заполнить std::map этими объектами, определение std::map таково:
std::map<int, Animation> animations;
Когда я пытаюсь заполнить карту, я делаю это так
void createAnimations(){
animations[0] = Animation(10);
animations[1] = Animation(10);
animations[2] = Animation(10);
animations[3] = Animation(10);
animations[4] = Animation(10);
}
Когда я запускаю программу, печатает это
+ *animation
+ animation
- animation
+ *animation
+ animation
- animation
+ *animation
+ animation
- animation
+ *animation
+ animation
- animation
+ *animation
+ animation
- animation
Почему эти дополнительные объекты создаются и уничтожаются?
`animations[0] = Animation(10);` Эта строка создает объект и вызывает оператор присваивания, а затем уничтожает объект. Какая у вас версия С++? В зависимости от этого есть лучший способ сделать.
Я использую С++17. Есть ли способ предотвратить конструкцию по умолчанию?
@Werem Я откатил правку, которая добавила код post-emplace. Если вы столкнулись с другой проблемой после изменения кода, вы должны опубликовать обновленный код как новый вопрос, а не обновлять этот вопрос: ваша новая проблема с emplace отличается от той, с которой вы столкнулись изначально.





Использование оператора квадратных скобок std::map или std::unordered_map приводит к созданию записи (с использованием конструктора по умолчанию) перед попыткой присвоения.
Возможно, лучше подумать об утверждении следующим образом:
animations[0] //operator[] invoked; default-constructed object created
= //Assignment operator
Animation(10); //Animation object constructed using Animation(int) constructor.
//Was created as an X-value, will be move-assigned into the default-constructed object
Если вы хотите вставить в карту без вызова ее конструктора по умолчанию, вам нужно использовать insert или emplace:
//May invoke move-constructor, may be elided, depending on how aggressively your compiler optimizes
animations.insert(std::make_pair(0, Animation(10));
animations.insert(std::make_pair(1, Animation(10));
animations.insert(std::make_pair(2, Animation(10));
animations.insert(std::make_pair(3, Animation(10));
animations.insert(std::make_pair(4, Animation(10));
//Will construct in-place, guaranteeing only one creation of the object
//Necessary if the object cannot be move or copy constructed/assigned
animations.emplace(0, 10);
animations.emplace(1, 10);
animations.emplace(2, 10);
animations.emplace(3, 10);
animations.emplace(4, 10);
Я использовал emplace и сделал трюк, чтобы предотвратить вызов конструктора по умолчанию, но теперь у меня есть дополнительный вызов деструктора для каждого вызова emplace.
Вам следует обратиться к ссылке на функцию, которую вы используете: en.cppreference.com/w/cpp/container/map/operator_at