While the end result of all 3 methods is the same (the string will be assigned to the variable), there are certain fundemental differences that go deeper than the syntax. I'll go over all 3 scenarios covered by your 3 strings:
The first case: s1 is an example of direct initialization. Direct initialization covers a number of difference scenarios, yours being defined as follows:
initialization with a nonempty parenthesized list of expressions.
Here, s1 does not have a class data type but a std::string
data type, so a standard conversion will take place to convert the data type in the parenthesis to the cv-unqualified version of s1, which is const *char
. Cv-unqualified means that there is no qualifier such as (const) or (volatile) attached to the variable. Note that in the case of a direct initialization, it is a lot more permissive than copy-initialization, which is the subject of s2. This is because copy-initialization will only refer to constructors and conversion functions defined by the user that are non_explicit (i.e implicit). On the other hand, direct-initialization considers implicit and explicit constructors and user-defined conversion functions.
Moving on, the second string, s2, is an example of copy initialization. Simply put, it copies the value from the left side to the right side. It is an example of:
when a named variable (automatic, static, or thread-local) of a non-reference type T is declared with the initializer consisting of an equals sign followed by an expression.
The process covered by this method is the same. Since s2 does not have a class data type but a std::string
data type, it will use the standard conversion to convert the value of the string on the right side to a value of type const *char
on the left. However, if the function is declared explicitly, the standard conversion cannot be made unlike the copy initializer, and the compilation of the code will fail.
See some examples of code comparing to 2 types of initializations. This should clear any confusions from above:
struct Exp { explicit Exp(const char*) {} }; // This function has an explicit constructor; therefore, we cannot use a copy initialization here
Exp e1("abc"); // Direct initialization is valid here
Exp e2 = "abc"; // Error, copy-initialization does not consider explicit constructor
struct Imp { Imp(const char*) {} }; // Here we have an implicit constructor; therefore, a copy initializer can be used
Imp i1("abc"); // Direct initialization always works
Imp i2 = "abc"; // Copy initialization works here due to implicit copy constructor
Moving on to the third case, it is not even a case of initialization, it is a case of assignment. Like you said in your comments, the variable s3 is initialized with a default string. That string is replaced by "Hello" when you use the equal sign to do so. What happens here is that when s3 is declared in string s3;
, the default constructor for std::string
is called, and a default string value is set. That default string is replaced by hello in the next line when you use the = sign.
If we are looking at which is more efficient in terms of speed when running, the difference is marginal. However, s1 takes the fastest time to run if we solely do this:
int main(void)
{
string a("Hello");
}
This took the following time and memory to compile and run:
Compilation time: 0.32 sec, absolute running time: 0.14 sec, cpu time: 0 sec, memory peak: 3 Mb, absolute service time: 0,46 sec
If we look at string s2 coded in the following way:
int main(void)
{
string a = "Hello";
}
Then the total time taken for the program to run is:
Compilation time: 0.32 sec, absolute running time: 0.14 sec, cpu time: 0 sec, memory peak: 3 Mb, absolute service time: 0,47 sec
The runtime using the copy initializer takes 0.01 seconds more to run than the direct initializer. Difference exists, but a marginal one.
The 3rd case with s3, if coded the following way:
int main(void)
{
string a;
a = "Hello";
}
Has a total running, compiling time and space taken of:
Compilation time: 0.32 sec, absolute running time: 0.14 sec, cpu time: 0 sec, memory peak: 3 Mb, absolute service time: 0,47 sec
I'd like to point something out here: the runtime difference between the second and third methods is most probably NOT zero; rather it is a time difference less than 0.01 seconds, with the 3rd method taking longer (s3). That is because it has 2 lines of code to operate on; one is the declaration of the variable and the other the assignment of the string to the variable.
Hope this answers your question.