I am learning C++ from the beginning and I don't get the whole strings topic.
What is the difference between the following three codes?
std::string s = std::string("foo");
std::string s = new std::string("foo");
std::string s = "foo";
I am learning C++ from the beginning and I don't get the whole strings topic.
What is the difference between the following three codes?
std::string s = std::string("foo");
std::string s = new std::string("foo");
std::string s = "foo";
std::string s = std::string("foo");
This creates a temporary std::string
object containing "foo", then assigns it to s
. (Note that compilers may elide the temporary. The temporary elison in this case is explicitly allowed by the C++ standard.)
std::string s = new std::string("foo");
This is a compiler error. The expression new std::string("foo")
creates an std::string
on the free store and returns a pointer to an std::string
. It then attempts to assign the returned pointer of type std::string*
to s
of type std::string
. The design of the std::string
class prevents that from happening, so the compile fails.
C++ is not Java. This is not how objects are typically created, because if you forget to delete
the returned std::string
object you will leak memory. One of the main benefits of using std::string
is that it manages the underlying string buffer for you automatically, so new
-ing it kind of defeats that purpose.
std::string s = "foo";
This is essentially the same as #1. It technically initializes a new temporary string which will contain "foo", then assigns it to s
. Again, compilers will typically elide the temporary (and in fact pretty much all non-stupid compilers nowadays do in fact eliminate the temporary), so in practice it simply constructs a new object called s
in place.
Specifically it invokes a converting constructor in std::string
that accepts a const char*
argument. In the above code, the converting constructor is required to be non-explicit
, otherwise it's a compiler error. The converting constructor is in fact non-explicit
for std::string
s, so the above does compile.
This is how std::string
s are typically initialized. When s
goes out of scope, the s
object will be destroyed along with the underlying string buffer. Note that the following has the same effect (and is another typical way std::string
s are initialized), in the sense that it also produces an object called s
containing "foo".
std::string s("foo");
However, there's a subtle difference between std::string s = "foo";
and std::string s("foo");
, one of them being that the converting constructor can be either explicit
or non-explicit
in the above case.
std::string s = std::string("foo");
This is called copy initialization. It is functionally the same as direct initialization
std::string s( "foo" );
but the former does require that the copy constructor is available and compilers may create a temporary object but most will elide the temporary and directly construct s
to contain "foo"
.
std::string s = new std::string("foo");
This will not compile because new
returns a pointer. To make it work you'd need the type of s
to be a std::string *
. Then the line dynamically allocates an std::string
object and stores the pointer in s
. You'll need to delete
it once you're done using it.
std::string s = "foo";
This is almost the same as first. It is copy initialization but it has an added constraint. It requires that the std::string
class contains a non-explicit
constructor that takes a const char *
. This allows the compiler to implicitly construct a temporary std::string
object. After that the semantics are identical to case 1.
s
new std::string("foo")
returns a pointer to some newly allocated memory.
For this to work, you should declare s as a pointer to a string std::string* s
.You should use the third option in most - if not all - cases.
1 will create a temporary variable (right hand side), then call the assignment operator to assign the value to s
2 will create an instance of std::string
on the heap and return a pointer to it, and will fail in the assignment because you can't assign a pointer to a non-pointer type
3 will build a std::string and initialize it from a const char*
On the number 1, you are creating a temporary string using the constructor and then assigning it to s. Number 2 doesn't even compile. On number 3, you are creating a new string and then assign a value to it.