push_back () e emplace_back () nos bastidores
Atualmente, estou aprendendo C ++ por conta própria e estou curioso sobre comopush_back()
eemplace_back()
trabalhar sob o capô. Eu sempre assumi queemplace_back()
é mais rápido quando você está tentando construir e empurrar um objeto grande para a parte traseira de um contêiner, como um vetor.
Vamos supor que eu tenho umStudent
objeto que eu quero acrescentar na parte de trás de um vetor de Students.
struct Student {
string name;
int student_ID;
double GPA;
string favorite_food;
string favorite_prof;
int hours_slept;
int birthyear;
Student(string name_in, int ID_in, double GPA_in, string food_in,
string prof_in, int sleep_in, int birthyear_in) :
/* initialize member variables */ { }
};
Suponha que eu chamepush_back()
e empurre umStudent
objeto até o final de um vetor:
vector<Student> vec;
vec.push_back(Student("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997));
Meu entendimento aqui é quepush_back
cria uma instância doStudent
objeto fora do vetor e depois o move para a parte de trás do vetor.
Também posso substituir em vez de push:
vector<Student> vec;
vec.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);
Meu entendimento aqui é que o objeto Student é construído na parte de trás do vetor, para que nenhum movimento seja necessário.
Assim, faria sentido que a colocação fosse mais rápida, especialmente se muitos objetos Student fossem adicionados. No entanto, quando cronometrei essas duas versões do código:
for (int i = 0; i < 10000000; ++i) {
vec.push_back(Student("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997));
}
e
for (int i = 0; i < 10000000; ++i) {
vec.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);
}
Eu esperava que o último fosse mais rápido, pois o grande objeto Student não precisaria ser movido. Curiosamente, oemplace_back
A versão acabou sendo mais lenta (em várias tentativas). Também tentei inserir 10000000 objetos Student, nos quais o construtor recebe referências e argumentos empush_back()
eemplace_back()
são armazenados em variáveis. Isso também não funcionou, pois o lugar ainda era mais lento.
Verifiquei para ter certeza de que estou inserindo o mesmo número de objetos nos dois casos. A diferença de horário não é muito grande, mas a substituição acabou mais lenta por alguns segundos.
Existe algo errado com meu entendimento de comopush_back()
eemplace_back()
trabalhos? Muito obrigado pelo seu tempo!
Aqui está o código, conforme solicitado. Estou usando o compilador g ++.
Empurre para trás:
struct Student {
string name;
int student_ID;
double GPA;
string favorite_food;
string favorite_prof;
int hours_slept;
int birthyear;
Student(string name_in, int ID_in, double GPA_in, string food_in,
string prof_in, int sleep_in, int birthyear_in) :
name(name_in), student_ID(ID_in), GPA(GPA_in),
favorite_food(food_in), favorite_prof(prof_in),
hours_slept(sleep_in), birthyear(birthyear_in) {}
};
int main() {
vector<Student> vec;
vec.reserve(10000000);
for (int i = 0; i < 10000000; ++i)
vec.push_back(Student("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997));
return 0;
}
Substituir de volta:
struct Student {
string name;
int student_ID;
double GPA;
string favorite_food;
string favorite_prof;
int hours_slept;
int birthyear;
Student(string name_in, int ID_in, double GPA_in, string food_in,
string prof_in, int sleep_in, int birthyear_in) :
name(name_in), student_ID(ID_in), GPA(GPA_in),
favorite_food(food_in), favorite_prof(prof_in),
hours_slept(sleep_in), birthyear(birthyear_in) {}
};
int main() {
vector<Student> vec;
vec.reserve(10000000);
for (int i = 0; i < 10000000; ++i)
vec.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);
return 0;
}