Stack Overflow Asked by Big Gorilla on November 4, 2021
In the below code
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a,c="!";
cin>>a;
int l=a.size();
for(int i=0;i<l;i++)
{
c=c+"#"+a[i];
}
cout<<c;
}
If I replace c=c+"#"+a[i]
with c+="#"+a[i]
i get unexpected output.
Output in the second case is !boxboxboxbox irrespective of input on https://www.onlinegdb.com/ .
On "dev c++" the output is –
But a += b is equivalent to a = a + b . Then what is the reason for the difference in output?
Fundamentally because C++ started its life as "C with classes". Over the years a bunch of new functionality was added and some rules were tightened but C++'s background as an extended C is still clearly visible. In particular.
std::string (strictly the std::basic_string template but lets ignore that detail for now) does it's best to help you. It defines sensible overloads for (again ignoring the detail of rvalue references).
But it can't do anything about operators where neither argument is a std::string. Those work in C++ in the same way they work in C.
The result of this is that order of operations becomes very important.
c=c+"#"+a[i];
is equivalent to c=((c+"#")+a[i]);
. This works fine, in the innermost operation one argument is a std::string so the overloaded operators do the right thing and concatenate the arguments to produce another std::string. The same applies when we concatenate the result of that innermost operation to the a[i]
c+="#"+a[i];
is functionally equivalent* to c=(c+("#"+a[i]));
so now we are trying to use the + operator between a string literal which evaluates to a char * and an operation which evaluates to a char. So we add the character code for the character at a[i] to the pointer to the string "#".
since "#" is a rather short string, this will almost certainly result in a pointer that is past the end of the string. This is undefined behaviour by the language spec.
I would guess that "!boxboxbox" is a sandbox error from onlinegdb. It has detected your code doing something it shouldn't and refused to let it go ahead.
Many compilers/linkers put different string data together, so on a regular compiler displaying (part of) another string from the executable (or libraries that it uses) is a likely outcome of running off the end of a string.
C++11 did add support for std::string literals, so one fix could be to add
using namespace std::string_literals;
Then change "#"
to "#"s
* Note that in general with overloaded operators in c++ "+" and "+=" are separate operators and nothing forces the implementer of the class to make them functionally equivalent. Sane class designers generally will though.
Also += may be more efficient as it may be able to perform the concatenation in-place rather than creating a new string.
Answered by plugwash on November 4, 2021
With c=c+"#"+a[i]
all the operators in the right of the expression are the same so the expression is processed from left to right, the first element is a std::string
to which a const char*
is added creating a new std::string
then add a char
creating another std::string
which is finally assigned to c
.
With c+="#"+a[i]
the right of the expression starts with a const char*
to which you add a char
, this invokes pointer arithmetic producing an invalid address which is then appended to the string c
which is undefined behaviour. To fix it you have to force the first argument to be a std::string
: c+=std::string("#")+a[i]
Answered by Alan Birtles on November 4, 2021
Given c+="#"+a[i];
, "#"+a[i]
is evaluated at first. "#"
is of type const char[2]
and could decay to pointer as const char*
, a[i]
is of type char
which is an integral type, then "#"+a[i]
just performs pointer arithmetic and won't concatenate strings as you expected. (And the result of pointer arithmetic might get out of the bound of the array and then leads to UB.)
On the other hand, in c=c+"#"+a[i];
, c+"#"
is evaluated at first, it appends "#"
on c
and returns a new std::string
(by operator+
for std::string
), on which a[i]
is appended and the result is assigned to c
.
But a += b is equivalent to a = a + b
If you put b
in integration, i.e. add parentheses as ("#"+a[i])
, then both c+=("#"+a[i]);
and c=c+("#"+a[i]);
yields the same result, even it's not what you expected.
Answered by songyuanyao on November 4, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP