“” +在C ++中的东西 [英] "" + something in C++
问题描述
我一直在我的代码中发生了很奇怪的事情。我相信我已经跟踪到标记为here的部分(代码被简化,当然):
std :: string func(){
char c;
//做分配给c
的东西return+ c; // Here
}
当我尝试<$ c时会发生各种事情$ c> cout 这个函数的结果。我想我甚至设法得到一些底层的C ++文档,以及许多细分错误。对我来说这显然不适用于C ++(我已经诉诸使用 stringstream
来执行转换 string
现在),但我想知道为什么。在使用大量的C#相当长一段时间后,没有C ++,这使我很痛苦。
-
是一个字符串文字。那些具有数组N
const char
。这个特殊的字符串是一个数组1const char
,一个元素是null终止符。 -
数组很容易衰减成指向它们的第一个元素的指针,例如
-
lhs + rhs
未定义为lhs
和整数rhs
。 -
char
是C ++核心语言的一个整数数据类型(即,作为整数)。
==> string literal +
字符因此被解释为指针 +
integer
表达式+ c
大致相当于:
static char const lit [1] = {'\0'};
char const * p =& lit [0];
p + c //+ c大致相当于这个表达式
您返回 std :: string
。表达式+ c
产生指向 const char
的指针。 std :: string
的构造函数期望一个 const char *
期望它是一个指向null终止字符数组。
如果 c!= 0
,则表达式+ c
会导致未定义的行为:
-
c& 1
,指针运算产生未定义行为。 -
如果
char $ c,则指针运算只在数组上定义,且结果是同一数组的元素。 $ c>已签名,则
c < c>,指针运算不会产生未定义的行为。这是一个特殊情况;指向一个元素超过数组的最后一个元素是允许的(它是不允许使用它指向的,虽然)。它仍然导致未定义的行为,因为
std :: string
构造函数在这里调用要求其参数是一个指向有效数组(和一个以null结束的字符串)的指针。一个过去的元素不是数组本身的一部分。违反此要求也会导致UB。
是 std :: string
的构造函数试图通过搜索数组中的第一个字符来确定传递它的以null结束的字符串的大小到'\0'
:
)
{
// simplified
char const * end = p;
while(* end!='\0')++ end;
// ...
}
,或者它创建的字符串包含垃圾。
也可能编译器假设这个未定义的行为将永远不会发生,并做一些有趣的优化,将导致奇怪的行为。
顺便说一下, clang ++ 3.5会为此代码段发出一个很好的警告: / p>
警告:向字符串添加'char'不会附加到字符串
[-Wstring-plus-int] p>
return+ c; // Here
~~~ ^ ~~
注意:使用数组索引警告
I've been having really freaky stuff happening in my code. I believe I have tracked it down to the part labeled "here" (code is simplified, of course):
std::string func() {
char c;
// Do stuff that will assign to c
return "" + c; // Here
}
All sorts of stuff will happen when I try to cout
the result of this function. I think I've even managed to get pieces of underlying C++ documentation, and many a segmentation fault. It's clear to me that this doesn't work in C++ (I've resorted to using stringstream
to do conversions to string
now), but I would like to know why. After using lots of C# for quite a while and no C++, this has caused me a lot of pain.
""
is a string literal. Those have the type array of Nconst char
. This particular string literal is an array of 1const char
, the one element being the null terminator.Arrays easily decay into pointers to their first element, e.g. in expressions where a pointer is required.
lhs + rhs
is not defined for arrays aslhs
and integers asrhs
. But it is defined for pointers as the lhs and integers as the rhs, with the usual pointer arithmetic.char
is an integral data type in (i.e., treated as an integer by) the C++ core language.
==> string literal +
character therefore is interpreted as pointer +
integer.
The expression "" + c
is roughly equivalent to:
static char const lit[1] = {'\0'};
char const* p = &lit[0];
p + c // "" + c is roughly equivalent to this expression
You return a std::string
. The expression "" + c
yields a pointer to const char
. The constructor of std::string
that expects a const char*
expects it to be a pointer to a null-terminated character array.
If c != 0
, then the expression "" + c
leads to Undefined Behaviour:
For
c > 1
, the pointer arithmetic produces Undefined Behaviour. Pointer arithmetic is only defined on arrays, and if the result is an element of the same array.If
char
is signed, thenc < 0
produces Undefined Behaviour for the same reason.For
c == 1
, the pointer arithmetic does not produce Undefined Behaviour. That's a special case; pointing to one element past the last element of an array is allowed (it is not allowed to use what it points to, though). It still leads to Undefined Behaviour since thestd::string
constructor called here requires its argument to be a pointer to a valid array (and a null-terminated string). The one-past-the-last element is not part of the array itself. Violating this requirement also leads to UB.
What probably now happens is that the constructor of std::string
tries to determine the size of the null-terminated string you passed it, by searching the (first) character in the array that is equal to '\0'
:
string(char const* p)
{
// simplified
char const* end = p;
while(*end != '\0') ++end;
//...
}
this will either produce an access violation, or the string it creates contains "garbage". It is also possible that the compiler assumes this Undefined Behaviour will never happen, and does some funny optimizations that will result in weird behaviour.
By the way, clang++3.5 emits a nice warning for this snippet:
warning: adding 'char' to a string does not append to the string [-Wstring-plus-int]
return "" + c; // Here ~~~^~~
note: use array indexing to silence this warning
这篇关于“” +在C ++中的东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!