简体   繁体   中英

Concatenation of std::string and int leads to a shift. Why?

Today I was surprised when trying to concatenate an std::string with an int . Consider the following MWE:

#include <iostream>
#include <string>

void print(const std::string& text)
{
    std::cout << "The string is: " << text << ".\n";
}

int main()
{
    print("iteration_" + 1);

    return 0;
}

Instead of printing

The string is: iteration_1.

which I would expect, it prints

The string is: teration_.

What exactly is going on in the background? Does the string for some reason get converted into char[] or something of the sort? The documentation of operator+ does not list any with an std::string and int .

And what is the proper way of concatenating an std::string with a number? Do I really have to throw them both into an std::stringstream or convert the number into std::string explicitely with std::to_string() ?

This line is the problem:

print("iteration_" + 1);

The string literal is decaying to a char* . You are adding 1 to this char* , moving it to the next character.

If you wanted to add the string "1" to the end of your literal, a fairly simple way is to pass the string literal to the std::string constructor and convert the 1 to a string manually. For example:

print(std::string("iteration_") + std::to_string(1));

Does the string for some reason get converted into char[]

Actually it is the other way around. "iteration_" is a char[11] which decays to a const char* when you add 1 . Incrementing the pointer by one makes it point to the next character in the string. This is then used to construct a temporary std::string that contains all but the first character.

The documentation you link is for operator+ of std::string , but to use that you need a std::string first.

"iteration_" is not std::string , but const char[] . Which decays to const char* , and "iteration_" + 1 just performs pointer arithmetic and move the pointer pointing to the next char (ie 't' ), then you got the c-style string "teration_" .

You can usestd::to_string to convert int to std::string , then concatenate them. eg

print("iteration_" + std::to_string(1));

For this case std::operator+(std::basic_string) is called and the 1st argument "iteration_" is converted to std::string implicitly and then passed to operator+ , then the concatenated std::string is passed to print .

LIVE

If you try to use the following:

std::string str = "iteration" + 1;

compiler will throw the warning:

warning: adding 'int' to a string does not append to the string [-Wstring-plus-int]

It is because you are incrementing the pointer to "iteration" string by 1 which means that now "teration" string is being assigned to str variable.

The proper way of concatenating would be:

std::string str = "iteration" + std::to_string(1);

The expression "iteration_" + 1 is a const char[11] literal added to the int 1.

In that expression, "iteration_" decays to a const char* pointer to the first element of the array. + 1 then takes place in pointer arithmetic on that pointer. The entire expression evaluates to a const char* type (pointing to the first t ) which is a valid NUL-terminated input to a std::string constructor! (The anonymous temporary std::string binds to the const std::string& function parameter.)

This is completely valid C++ and can occasionally be put to good use.

If you want to treat + as a concatenation, then

print("iteration_" + std::to_string(1));

is one way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM