在C++中:如果我们给字符串添加一些整数,为什么它会从开头删除相应数量的字符?(string+int)

3

这是我的程序!我想知道输出背后的原因。

#include <iostream>
using namespace std;

class A{
  public:
      void fun(int i){
          cout<<"Hello World" + i<<endl;
      }
};

int main()
{
  A obj1;
  obj1.fun(2);

  return 0;
}

预期输出: Hello World2

实际输出: llo World

PS:为了打印出“HelloWorld2”,我还可以编写 cout<<"Hello World"<< i 的代码。


您需要的是Java,而不是C++。在C++中,正确的方法是使用cout<<"Hello World"<< i。预期输出为:Hello World2。 - PaulMcKenzie
自从C++14以来,您可以使用"Hello World"s + i。在C++11中,类似的事情可以通过用户定义字面量完成。 - phuclv
1
@LưuVĩnhPhúc应该使用"Hello Worls"s + std::to_string(i)以避免UB。 - StoryTeller - Unslander Monica
4个回答

6
"Hello World"不是std::string,它是一个字符串字面量,因此它的类型是const char[]。当像您在此处使用i一样添加整数时,实际上正在创建一个临时的const char*,该指针首先指向const char[]的第一个元素,即'H',然后将其移动2个位置(因为i为2),因此它指向'l',然后将该指针传递给cout,因此cout从'l'开始打印。对此类类型执行二进制操作称为指针算术。
为了更好地理解,使用一个示例char数组,您的代码底层类似于:
const char myHello[] = "Hello World";
const char* pointer = myHello; // make pointer point to the start of `myHello`
pointer += i; // move the pointer i spots
cout<< pointer <<endl; // let cout print out the "string" starting at the character pointed to by the new pointer.

请注意,如果您试图将指针“移动”得太远,以至于它指向字符串之外的某些内容,然后尝试访问此指针,则会出现未定义行为。与访问越界数组的方式相同,这也是UB。只需确保index < size即可。

向右移动两个位置会得到“llo World”,正如问题中观察到的那样(没有发生i-1)。 - chtz
@chtz 嗯,正在编辑,谢谢。 - Hatted Rooster
@GillBates 谢谢您的回答。它确实帮助我深入理解! - reverie_ss

2

"Hello World" + i 不能进行字符串拼接,它只会进行指针算术运算。

它获取c字符串字面量"Hello World"的地址,我们称之为a。 然后将其加上a + i。当i大于c字符串字面量的长度时,对结果指针进行解引用是未定义行为。

但如果在范围内,则会得到字面量内部的地址,这将在打印时显示为后缀。然而,由于c字符串字面量是const的,因此尝试写入该地址也会再次导致未定义行为。

长话短说,不要这样做。


1
""Hello World"被编译为字符数组,并作为指向这些字符的指针传递给operator<<。然后,您将i添加到指针上,这将使指针移动那么多个字符。"

1
指针算术。 "Hello World" 是一个字符串文字,由 const char* 隐式指向。
将整数 i 添加到指针中将使其向前移动 i 个位置(如果 i<0,则向后移动)。
因此,"Hello World" + 2 的结果是一个常量指针(const char*),指示字符串中第三个字母的地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接