Recently in writing a piece of code, suddenly very curious c++11 in the push_back have any improvement to increase efficiency, Internet search some information, found that really new Emplace_back method, than push_back efficiency is much higher.
First, write a class for timing,
Time_interval.h#pragma once#include <iostream>#include <memory>#include <string>#ifdef GCC#include <sys/time.h>#else#include <ctime>#endif//GCCClasstimeinterval{Public:timeinterval (CONST STD::string& d): detail (d) {init ();} TimeInterval () {init ();} ~timeinterval () {#ifdef GCC gettimeofday (&end, NULL); Std::cout << Detail <<+ * (end.tv_sec-start.tv_sec) + (END.TV_USEC-START.TV_USEC)/<<"MS" << Endl;#else end = Clock (); Std::cout << Detail << (Double) (End-start) << "MS" << Std::endl; #endif//gcc}protected: void init () {#ifdef GCC gettimeofday (&start, NULL); #else start = clock (); #endif//GCC} private:std::string detail; #ifdef GCC timeval start, end; #else clock_t start, end; #endif//GCC}; #define Time_interval_scope (d) std::shared_ptr<timeinterval> time_interval_scope_begin = Std::make_ Shared<timeinterval> (d)
The use of the method is to use the macro Time_interval_scope (d) in the scope, d for the printed string, the output scope of the time-consuming situation.
Second, take a look at the time-consuming comparisons of the 5 methods of push to vector:
#include <vector>#include <string>#include "time_interval.h"int main () {STD::vector<STD::String> v;int count =10000000; V.reserve (count);Pre-allocate 100,000 size, excluding time allocated for memory {Time_interval_scope ("Push_back string:");for (int i =0; I < count; i++) {STD::String Temp ("Ceshi"); V.push_back (temp);Push_back (const string&), parameter is Lvalue reference}} v.clear (); {Time_interval_scope ("Push_back Move (String):");for (int i =0; I < count; i++) {STD::String Temp ("Ceshi"); V.push_back (Std::move (temp));Push_back (string &&), parameter is rvalue reference}} v.clear (); {Time_interval_scope ("Push_back (String):");for (int i =0; i < count; i++) {V.push_back (std::string ( " Ceshi ")); //push_back (String &&), argument is rvalue reference}} V.clear (); {Time_interval_scope ( "push_back (C string):"); for (int i = 0; i < count; i++) { V.push_back ( "Ceshi"); Push_back (string &&), parameter is rvalue reference}} v.clear (); {Time_interval_scope ( "Emplace_back (C string):"); for (int i = 0; i < count; i++) { V.emplace_back ( "Ceshi"); Only once constructor, do not call copy constructor, fastest}}}
VS2015 release under compile, run result:
Push_back string:327 ms
Push_back Move (String): 213 ms
Push_back (String): 229 ms
Push_back (c string): 215 ms
Emplace_back (c string): 122 ms
The 1th method takes the longest, for obvious reasons, the push_back of the Lvalue reference will be called, and the copy constructor of string will be called once, which is time consuming, and the string here is very short, and if it is long, the difference will be greater.
The method in 2nd, 3, and 4 is basically the same, the parameter is the right value, the push_back of the rvalue reference is called, so the move constructor of string is called, and the move constructor takes less time than the copy constructor because there is no need to reallocate memory space.
The 5th method takes the least time because Emplace_back only calls the constructor, there is no move constructor, and no copy constructor.
To substantiate this assertion, we customize a class and print the corresponding description in the ordinary constructor, copy constructor, and move constructor:
#include <vector>#include <string>#include "time_interval.h"Class Foo {Public:foo (STD::String str): Name (str) {STD::cout <<"Constructor" <<Std::endl; } Foo (Const foo& F): Name (f.name) {STD::cout <<"Copy Constructor" <<Std::endl; } Foo (foo&& f): Name (Std::move (F.name)) {STD::cout <<"Move Constructor" <<Std::endl; }PrivateSTD::string name;};int main () {STD::Vector<foo> v;int count =10000000; V.reserve (count);Pre-allocate 100,000 size, excluding time allocated for memory {Time_interval_scope ("Push_back T:"); Foo Temp ("Ceshi"); V.push_back (temp);Push_back (const t&), parameter is lvalue referencePrinting results:ConstructorCopy constructor} v.clear (); {Time_interval_scope ("Push_back Move (T):"); Foo Temp ("Ceshi"); V.push_back (Std::move (temp));Push_back (T &&), parameter is rvalue referencePrinting results:ConstructorMove constructor} v.clear (); {Time_interval_scope ("Push_back (t&&):"); V.push_back (Foo ("Ceshi"));Push_back (T &&), parameter is rvalue reference//print Result: //constructor //move constructor} v.clear (); {std::string temp = "Ceshi"; Time_interval_scope ( "push_back (string):"); V.push_back (temp); //push_back (T &&), parameter is rvalue reference //print Result: //constructor //move constructor} v.clear (); {std::string temp = "Ceshi"; Time_interval_scope ( "Emplace_back (string):"); V.emplace_back (temp); //only once constructor, do not call copy constructor, fastest //print Result: //constructor}}
Conclusion: In the case of c++11, Emplace_back instead of push_back is decisive.
C++11 using Emplace_back instead of push_back