Initialization .. which one is more efficient?

I have the following question. Which one is better, which should be followed and why?

string strMyString = "SampleString"; 

or

 string strMyString("SampleString"); 

Thanks in advance.

+7
c ++ constructor initialization
source share
4 answers

I answered it here

One thing I introduced into this answer here: No assignment operator uses.

A brief explanation for a specific line. std::string has a constructor that takes one argument, which takes char const* :

 // simplified to a normal class declaration. std::string actually // is a template instantiation. class string { public: string(char const* str) { // copy over... } }; 

Now you see that the constructor has a pointer to the character (s). So that he can take a string literal. I think the following case is obvious:

 string s("hello"); 

It will invoke the constructor directly and initialize s thereby. This is called direct initialization.

Another way to initialize a variable is called copy initialization. The standard says for the case of copy initialization, when the initializer does not have the type of the object being initialized, the initializer is converted to the corresponding type.

 // uses copy initialization string s = "hello"; 

Specify Types First

  • s is of type std :: string
  • "hello" is an array, which in this case is again treated as a pointer. Therefore, we will consider it as char const* .

The compiler is looking for two ways to do the conversion.

  • Is there a conversion constructor to std :: string?
  • Does the initializer have a type that has a conversion operator function that returns std::string ?

It will create a temporary std::string one of these ways, which will then be used to initialize the s object using the std::string copy constructor. And he sees that std::string has a conversion constructor that the initializer accepts. So it uses. In the end, it’s actually the same as

 std::string s(std::string("hello")); 

Note that the form that is used in your example that caused all this

 std::string s = "hello"; 

defines an implicit conversion. You can mark the constructor by specifying char const* as explicit for your types if you are wondering about the initialization rules for your material, and it will no longer be able to use the corresponding constructor as the conversion constructor:

 class string { public: explicit string(char const* str) { // copy over... } }; 

At the same time, initialization using copy initialization and a char const* actually prohibited (and in other places)!

Now, if the compiler does not support the allocation of temporary files in different places. The compiler is allowed to assume that the copy instance is copying in this context and can exclude an additional copy of the temporary string and instead create a temporary std :: string directly into the initialized object. However, the copy constructor must be available in particular. So copy initialization is invalid if you do this

 class string { public: explicit string(char const* str) { // copy over... } private: // ugg can't call it. it private! string(string const&); }; 

Now, in fact, only the case with direct initialization is valid.

+19
source share

Compile both options, look at the assembler. The first is fewer instructions ...

 ; 9 : std::string f("Hello"); push OFFSET ??_C@_05COLMCDPH@Hello?$AA@ lea ecx, DWORD PTR _f$[esp+80] call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z ; 10 : std::string g = "Hello"; push OFFSET ??_C@_05COLMCDPH@Hello?$AA@ lea ecx, DWORD PTR _g$[esp+80] mov DWORD PTR __$EHRec$[esp+88], 0 call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z 

... but this is an artifact because it was the first that the compiler saw. Change the code by replacing the order:

 ; 9 : std::string g1 = "Hello"; push OFFSET ??_C@_05COLMCDPH@Hello?$AA@ lea ecx, DWORD PTR _g1$[esp+136] call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z ; 10 : std::string f1("Hello"); push OFFSET ??_C@_05COLMCDPH@Hello?$AA@ lea ecx, DWORD PTR _f1$[esp+136] mov DWORD PTR __$EHRec$[esp+144], 0 call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z 

... and now, the second is fewer instructions.

We also see that this compiler (Microsoft VC ++ 2005, Release settings) created the same assembler for both versions. Therefore, it does not make any difference in this compiler, and you can prove it.

+7
source share

The only real difference is that the first of them technically requires the use of a copy constructor, but the compiler is allowed to exclude it so that the efficiency is the same in both cases.

However, the former requires the copy constructor to be accessible (i.e., not private), even if it is not actually used.

+2
source share

Other answers are correct, but please also remember that this probably does not matter. It will be rare, very rare, incredibly rare that the efficiency of line initialization will ever affect your program speed even for a split second.

The question itself is fun , because it helps to show the operations of C ++ constructors and assignments, but in practice, if you spend time on optimization (and publishing on SO is proven enough ..), you really lean on windmills.

It is better to avoid distraction and waste your strength elsewhere.

+1
source share

All Articles