push_back () y emplace_back () detrás de escena

Actualmente estoy aprendiendo C ++ por mi cuenta, y tengo curiosidad acerca de cómopush_back() yemplace_back() trabajar debajo del capó. Siempre he asumido queemplace_back() es más rápido cuando intenta construir y empujar un objeto grande hacia la parte posterior de un contenedor, como un vector.

Supongamos que tengo unaStudent objeto que quiero agregar al reverso de un vector de Estudiantes.

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 */ { }
};

Supongo que llamopush_back() y empuje unStudent objeto al final de un vector:

vector<Student> vec;
vec.push_back(Student("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997));

Mi entendimiento aquí es quepush_back crea una instancia deStudent objeto fuera del vector y luego lo mueve a la parte posterior del vector.

Diagrama:

También puedo colocar en lugar de presionar:

vector<Student> vec;
vec.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);

Mi comprensión aquí es que el objeto Estudiante se construye en la parte posterior del vector para que no se requiera movimiento.

Diagrama:

Así, tendría sentido que la colocación fuera más rápida, especialmente si se agregan muchos objetos de Estudiante. Sin embargo, cuando cronometré estas dos versiones de código:

for (int i = 0; i < 10000000; ++i) {
    vec.push_back(Student("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997));
}

for (int i = 0; i < 10000000; ++i) {
    vec.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);
}

Esperaba que este último fuera más rápido, ya que el gran objeto Estudiante no tendría que ser movido. Por extraño que parezca, laemplace_back versión terminó siendo más lenta (en múltiples intentos). También intenté insertar 10000000 objetos de estudiante, donde el constructor toma referencias y argumentos enpush_back() yemplace_back() se almacenan en variables. Esto tampoco funcionó, ya que el emplazamiento aún era más lento.

Lo he comprobado para asegurarme de que estoy insertando la misma cantidad de objetos en ambos casos. La diferencia horaria no es demasiado grande, pero el emplazamiento terminó más lento en unos segundos.

¿Hay algún problema con mi comprensión de cómopush_back() yemplace_back() ¿trabajo? ¡Muchas gracias por tu tiempo

Aquí está el código, según lo solicitado. Estoy usando el compilador de g ++.

Hacer retroceder

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;
}

Emplace atrá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.emplace_back("Bob", 123456, 3.89, "pizza", "Smith", 7, 1997);
    return 0;
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta