为什么 std::string 对象在使用默认构造函数构造时表现不同?

Why std::string object when constructed with default constructor behaves differently?

我尝试了以下程序:

#include <iostream>
#include <string>

int main ()
{
  std::string str;
  str[0] = 'o';
  str[1] = 'k';
  std::cout << str.length();
  std::cout << "as a whole :";
  std::cout << str << std::endl;
  std::cout << "character by character :";
  std::cout << str[0] << str[1] << std::endl;      
  return 0;
}

我不明白为什么我不能使用对象变量打印整个字符串以及为什么长度 returning 为 0 因为很明显我已经使用下标添加了字符运算符,因为 return 字符引用所以我知道这是合法的。

此外,我没有得到任何异常。所以就是这样。显然,std::string class 的幕后发生了很多事情,我知道我遗漏了一些东西。有人可以帮我解决这个问题吗?

I don't understand why I can't print the string as a whole [...]...

因为您正在经历 未定义的行为

这个

std::string str;

使用 0 内存分配构造默认字符串。意思是通过 std::string::operator[] 修改将导致 asses out of bounds undefined behaviour。因此,任何事情都有可能发生。在你的例子中,长度 returns 0


[...] clearly I have added the characters using the subscript operator as that would return char reference so I know that is legal.

没有,你没有,原因如上。作为参考,std::string::operator[]

Returns a reference to the character at specified location pos. No bounds checking is performed. If pos > size(), the behavior is undefined.


作为可能的修复,您可能希望 std::string::resize 之前访问元素。

#include <string>

std::string str;
str.resize(2);
str[0] = 'o';
str[1] = 'k';
// ... now it has defined behaviour

std::string::push_back 将每个字符放入字符串中。

#include <string>

std::string str;
str.push_back('o');
str.push_back('k');
// ... now it has defined behaviour

您有一个长度为 0 的字符串,然后您尝试使用下标运算符修改其内容。这是未定义的行为,所以在这一点上,不能保证特定的结果。如果您改用 at(),它会暴露错误并引发异常。

why the length is returning as 0

开始时是 0,您没有做任何添加(例如 push_back+=)。但是话又说回来,因为你之前所做的是未定义的行为,所以这里可能发生任何事情。

In addition, I didn't get any kind of exception.

您可以尝试 std::string::at,当您尝试时会抛出 std::out_of_range 异常。

您没有向空字符串 str 添加任何内容。相反,您正在尝试编辑空字符串的不存在元素。 std::string 的下标运算符不会自动添加元素。 (与 std::map 不同)此外,不能保证下标运算符会抛出一些异常。如果你想要safe-subscript-operation,你可以使用std::string::at函数。

您可以使用 += 运算符将内容附加到您的字符串。

str += 'o';
str += 'k';