What's the difference between "" and {} for initializing an empty string? - c++

string a = "";
string b = {};
I couldn't really find a good reference explaining the difference between them. Does a compiler see them differently? Then, why?

a is constructed using copy initialisation.
b is constructed using copy list initialisation.
For a std::string the compiler will produce the same thing; a zero length string.
But the mechanism by which the string is constructed may well be different - a compiler, conceptually at least, will have to traverse the anonymous temporary const char[] passed to construct a.
For other types there may be differences; research the two terms above for more details.

In this case, no difference.
string b = {};
initializes the string with the type's default value, which is an empty string.
string a = "";
initializes the string with a specific value, which happens to also be an empty string.
Note that just doing string c; would also create an empty string.

Related

Function call parameter, char * vs string default constructor

While calling a function/method in C++11 and above, which one is better (if any difference)?
Lets assume this function/method:
void func(std::string s) { ... }
Which one is best between the following?
func(std::string())
or
func("")
And more generally, is there any advantage to always call the constructor explicitly during initialization or parameter passing?
It's better to call the default constructor, because it's guaranteed to not do any unnecessary work.
When passing an empty string literal, it could be that the string implementation does some work processing that string (compute its length for example). An empty string literal isn't a magic bullet that can be treated differently from non-empty string literals. It's type is const char[1], which decays into const char*, and that's it - the std::string constructor dealing with this literal will end up doing more work than necessary.
From cppreference for std::string::string():
Default constructor. Constructs empty string (zero size and unspecified capacity). If no allocator is supplied, allocator is obtained from a default-constructed instance.
... and for std::string::string(const char*):
Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. [...]
For further reading, see also this short article.
I would like to compare func(std::string()) with func(""):
func(std::string())
You create an std::string object with default parameter is empty string
Then pass std::string object to func function. You pass it by value, and a new std::string object will be allocated in stack memory, and call a copy constructor to initialized it.
In this case, there are two std::string object is allocated.
func("")
You pass an empty string, so compiler will allocate a std::string object in stack memory, and use std::string(const char*) constructor.
In this case, there is only 1 std::string object allocated.
So, I think for this specific case, func("") maybe better.

String data type variable initialization

How to initialize a string data type variable by null character('\0')???
string txt='\0';
is it right or wrong?
This is wrong, because there is no constructor of std::string which takes char. If you want to construct an std::string which has a null-terminator in it (for whatever reasons you might have) you should use different constructor:
std::string txt(1, '\0');
Please note, this is the answer which takes question on it's face value. You probably do not need this at all, but I do not know that for sure.
First of all understand that to make std::string::c_str() work, std::string always allocates space for terminating zero, so most probably default constructor will do the job for you.
On other hand if you need string which length is not zero and contains zero inside there are two approaches.
use std::string txt(1, '\0'); as #SergeyA sucgested in other ansewear. (this will work with old C++03)
use string literal suffix operators, which is more handy IMO.
.
using namespace std::literals::string_literals;
auto s2 = "\0"s;
Here is live example.

Which std::string constructor is being called here?

I am trying to construct a string in C++ as below.
const char *cstring = "abcd";
const string cppstr = string(cstring, cstring + strlen(cstring));
This is working fine and cppstr has the value "abcd" even though it doesn't match with any of the string constructors specified in the standard. Can any one please let me know which constructor of string is invoked in this particular case.
There is a templated constructor that takes as its input two InputIterators. (See the cppreference.org reference, constructor (6)). Raw C++ pointers meet all the requirements of InputIterators (in fact, they're RandomAccessIterators). Therefore, calling
string(cstring, cstring + strlen(cstring)
invokes this constructor. That constructor works by iterating across the range of the elements delineated by the iterator and constructing a string as a copy of those elements.
As a note, you can also just write
const string cppstr{cstring, cstring + strlen(cstring)};
here instead of assigning cppstr a value.

C++, strings, and pointers

I know this is rudimentary but I know nothing about C++. Is it necessary to do:
string *str = getNextRequest();
rather than
string str = getNextRequest();
in order to reference str later on in the same block of code? If so, what type of error would the latter produce?
That depends entirely on the return type of getNextRequest.
Strings can be used and reused throughout the scope they're declared in. They essentially contain a mutable C string and some handling information, helper methods, etc.
You can, very safely, return a string from a function and the compiler will make a copy or move it as necessary. That string (str here) can then be used normally, with no worries about using out-of-scope locals or such.
There are times when a pointer to a string is needed, but unless you're using it as an out parameter, those tend to be rare and indicate some design oddity.
Which you use depends on what getNextRequest() returns. If it returns a string *, then use the first line, if it returns string then use the second.
So if the declaration of getNextRequest is like this:
string getNextRequest();
Then
string str = getNextRequest();
is correct. If the declaration is like this:
string *getNextRequest();
Then you can go with
string *str = getNextRequest();
or
string str = *getNextRequest();
string str = getNextRequest();
will create a copy of the string returned by getNextRequest. If you want to alter the contents of str and wish that these changes are also within the string returned by getNextRequest you have to return a pointer or reference.
If this is what you want, then you should define getNextRequest as:
string& getNextRequest()
and use it like:
string& str = getNextRequest();
string str* = getNextRequest();
As noted by #dasblinkenlight, that would be a syntax error
But to answer your original question, is it necessary? No. In general, you should not use pointers unless you must.
Especially with the STL. The STL is not designed to be used with pointers--it does dynamic memory management for you. Unless you have a good reason, you should always use vector<int> v and string s rather than vector<int>* or string*.
You will probably need to provide a little bit more information regarding this function getNextRequest(). Where is it from? Library? API? Purpose?
If the return type of the function is a string* (pointer to str), then the string has been allocated to the "heap". This means, it does not matter which block of code you reference the string from. As long as you maintain the pointer, you will be able to access it.
If the return type of the function is simply a string (meaning not a pointer), it will return the value, not the address of str. In essence, you would be "copying" the string to your new variable. In this case, the variable would be allocated on the stack, and you would only be able to reference it when in the scope of the code block.

C++ string declaration

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::strings, so the above does compile.
This is how std::strings 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::strings 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.
Creates a temporary string object and copies the value to s
Does not compile, 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.
Constructs a string from a C-string.
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.