Поскольку ваш код стоит (и как указано в комментариях), когда вы инициализируете массив arr[4]
, компилятор скопирует каждый объект в списке инициализатора на цель - отсюда вызов конструктор копирования четыре раза.
Один из способов избежать этого - использовать std::move(x)
в списке инициализатора, но для этого вам нужно будет предоставить конструктор перемещения для вашего player
класса (в вашем случае будет достаточно по умолчанию).
Однако помните, что после перемещения от объекта исходный объект больше не обязательно будет тем же самым как это было и использование его может быть недействительным. Единственное требование после перемещения (хотя класс может дать больше гарантий), чтобы объект находился в состоянии, когда его можно безопасно уничтожить. (Спасибо за комментарий от Jesper Juhl к этой заметке!)
Этот код даст ожидаемый результат:
#include <iostream>
#include <utility> // Defines std::move()
using std::string;
using std::cout; using std::endl;
class player {
public:
int xp;
string name;
int health;
player() :player(0, 0, "none") {}
player(int a) :player(a, 0, "none") {}
player(int a, int b, string c) :name{ c }, xp{ a }, health{ b } {}
player(player& source) {
name = "copied player";
xp = -1;
health = -1;
}
player(player&& p) = default; // Use the compiler-generated default move c'tor
};
int main()
{
player p1;
player p2(2);
player p3(2, 5, "play3");
player copy{ p2 };
// player arr[4]{ p1,p2,p3,copy };
player arr[4]{ std::move(p1), std::move(p2), std::move(p3), std::move(copy) };
int t = 4;
while (t--) {
cout << arr[3 - t].name << endl;
cout << arr[3 - t].xp << endl;
cout << arr[3 - t].health << endl;
}
return 0;
}
Примечание: Пожалуйста, прочитайте также: Почему "использование пространства имен std;" считается плохой практикой? .