Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between these two cases of adding a string?

Tags:

c++

string

c++11

I noticed that when I initialized a string, the compiler reported an error that I was not expecting.

For example:

#include <iostream>
#include <string>

using namespace std;

int main() {
    string s1 = "Hello", s2 = "World!"; // ok
    string s3 = s1 + ", " + "World!"; // ok
    string s4 = "Hello" + ", " + s2; // error
    cout << s1 + " " + s2 << endl; //ok
    return 0;
}

For me, if s3 worked just fine, s4 should do the same.

Why do I get that error? What is the difference between these two initialization strings (s3 and s4)?

like image 216
Gabriel Avatar asked Sep 13 '15 22:09

Gabriel


People also ask

What is the difference between string and new string?

String(String original) : Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string.

What is the difference between creating string as new () and literal?

4. String Literal vs String Object. When we create a String object using the new() operator, it always creates a new object in heap memory. On the other hand, if we create an object using String literal syntax e.g. “Baeldung”, it may return an existing object from the String pool, if it already exists.

What is the difference between string and string literals?

String literals or constants are enclosed in double quotes "" or with @"". A string contains characters that are similar to character literals: plain characters, escape sequences, and universal characters.

How can I compare two strings in C++?

In order to compare two strings, we can use String's strcmp() function. The strcmp() function is a C library function used to compare two strings in a lexicographical manner. The function returns 0 if both the strings are equal or the same.


2 Answers

"Hello" is not a std::string (rather it is a const char[6], while ", " is a const char[3]) and the + operator for std::strings does not apply.

This is a minor inconvenience of C++ and stems from its C ancestry. It means that in concatenating strings via + you must ensure that at least one of its two operands actually is a std::string, as in

auto s = std::string{"Hello"} + ", " + "World";

where the first + has a std::string as its first operand and hence produces a std::string, so that the second + also has a std::string as its first operand (since + is processed from left to right).


Edit1 prompted by the comment by T.C., I mention that C-string literals are automatically concatenated if only separated by white space:

std::string s = "Hello" ", " "World";

This behaviour too is inherited from C: the preprocessor renders above code to

std::string s = "Hello, World";

before the compiler proper processes it (to be more precise, string concatenation takes place in phase 6 of translation, just before compilation). This is in fact the most simple and hence most convenient way to concatenate raw string literals. But note that I had to declare the type of s, since auto deduction would have given a const char*.


Edit2 prompted by the comment by PaperBirdMaster, I mention that since C++14, you can directly form std::string literals by simply adding s after the string, if you pull in the associated operator""s (or surrounding namespace).

using std::literals::operator""s;                // pull in required operator
const auto s = "Hello"s + ", " + "World";        // std::string

See this post as to why the required operator""s is hidden in the nested namespace. Note also that alternatively to using std::literals::operator""s; you may pull in the surrounding namespace: either of the following declarations will do.

using namespace std::string_literals;
using namespace std::literals::string_literals;
using namespace std::literals;

which are not as bad (and damned) as plain using namespace std;.

like image 179
Walter Avatar answered Oct 19 '22 03:10

Walter


The following line attempts to add 2 pointers together.

string s4 = "Hello" + ", " + s2; // error

"Hello" is a const char[6] which decays to const char* and ", " is a const char[3] which decays to const char*.

You are trying to assign the addition of two pointers to a std::string, which is not valid. Furthermore, the addition of two pointers is not valid either.

As other people have said, this doesn't have anything to do with the overloads of operator+ of the std::string class, as the following code would also not compile for the same reason:

string s4 = "Hello" + ", ";

I have added some clarifications provided by user @dyp.

You can fix your problem by using the C++ Standard Library "user-defined" string literal. The functionality is provided by std::literals::string_literals::operator""s which is found in the <string> header. You might have to use a using-directive or -declaration; this was not required on my compiler and including the <string> header was enough. Example:

string s4 = "Hello"s + ", "s + s2;

This is the equivalent of:

string s4 = std::string("Hello") + std::string(", ") + s2;

When you place an instance of std::string as the first operand, the rest of the expression will use that type, because of left to right associativity for operator+ will make sure that an instance of std::string is returned as the left-most operand every time, instead of const char*. That is why you have no error on line:

string s3 = s1 + ", " + "World!";

That line is equivalent to:

string s3 = ((s1 + ", ") + "World!");
like image 23
bku_drytt Avatar answered Oct 19 '22 02:10

bku_drytt