为什么 std::string 在索引超出范围时不自动追加(或崩溃)?
Why doesn't std::string automatically append (or crash) when the index is out of range?
我是C++新手,我有一些 C 经验,我很高兴看到 std::string 作为 char[] 的替代品。在我的学习过程中,我写了一个看起来像这样的函数:
std::string constToLowercase(const std::string &s){
std::string newString = "";
for (int i = 0; i < s.length(); i++){
newString[i] = tolower(s[i]);
}
return(newString);
}
目标是接受字符串并返回小写版本,而不会影响原始字符串。 我发现这个函数总是返回一个空字符串。我想这是因为我正在索引到字符串尚未保留的内存中,但我本来希望出现异常或程序崩溃,而不是简单地返回任何内容。
我的下一个想法是尝试这个(在第 2 行更改):
std::string constToLowercase(const std::string &s){
std::string newString = s;
for (int i = 0; i < s.length(); i++){
newString[i] = tolower(s[i]);
}
return(newString);
}
这是成功的,显然是解决我问题的好方法。
不过,我对自己的缺乏理解感到不安,在试图弄清楚为什么我的原始功能不起作用时,我尝试了这个(第 2 行的更改已还原,第 4 行的更改):
std::string constToLowercase(const std::string &s){
std::string newString = "";
for (int i = 0; i < s.length(); i++){
newString = newString + static_cast<char>(tolower(s[i]));
}
return(newString);
}
这个函数按照我预期的函数 1 工作。我的问题是为什么函数 1 不像函数 3?作为后续行动,为什么函数 1 不会崩溃?
C++尝试为您提供具有更高级别类型的原始 C 级性能。
它将某些内容保留为未定义的行为,并且不检查边界,因为这会减慢速度。
通常有一些 API 更安全,例如在越界时抛出的.at
。
还有别的东西 - 它应该用什么填充? (一个空间? 空? 它应该如何处理访问元素2^60
? 这些都是很难完美回答的问题。
您可以轻松编写自己的函数,完全按照自己的要求执行。 这并不难。 然而,如果他们把它烤成std::string
,你将永远无法获得"原始金属"的性能。
我的问题是为什么函数 1 不像函数 3?
因为std::basic_string::operator[]
的文档是这样说的:
返回对指定位置处字符的引用。 不执行边界检查。如果 pos> size(),则行为未定义。
作为后续行动,为什么函数 1 不会崩溃?
因为未定义的行为并不意味着崩溃。它可能会崩溃,也可能不会。它肯定不会做什么 - 始终正常工作。
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 为什么 std::string 在索引超出范围时不自动追加(或崩溃)?
- C++字符串数组追加的目标C++崩溃
- 应用程序在向字符串追加数据时崩溃