c++ - 类动态分配的字符数组中的 WTF 行为
问题描述
每次运行下面的代码时,我都会崩溃应用程序。在调试过程中,我看到该str
对象在main()
. 这对我来说是个谜。尝试自己运行它:
#include<iostream>
class String {
private:
char* string = nullptr;
int length = 0;
public:
String(const char str[]) {
for (length; str[length] != '\0'; ++length);
string = new char[length + 1]{};
for (int i{}; i < length; ++i)
string[i] = str[i];
string[length] = '\0';
}
~String() {
delete[] string;
}
auto print() {
for (int i{}; i < length; ++i)
std::cout << string[i];
std::cout << '\n';
return *this;
}
auto getStrPtr() {
return string;
}
};
int main() {
String str("123");
auto strPtr{ str.print().getStrPtr() };
strPtr[0] = '3';
}
我错过了什么吗?
注意第 2 行main()
:我正在尝试打印str
'string
数组,然后,由于print()
返回*this
,我可以链接方法并调用返回string
' 指针的函数。但是,即使在调试器中它都能完美执行,我也不知道为什么地狱str
对象会在之后解构自己。
解决方案
str
对象不会在 的第二行被销毁main
。的临时副本str
被销毁。
临时对象在完全表达结束时被销毁。这个是正常的。
您的类在析构函数中删除了一个指针成员,但未能保持该指针唯一性的类不变性。str
当析构函数删除与临时对象的析构函数删除相同的指针值时,程序的行为是不确定的。strPtr[0] = '3';
甚至在此之前,当通过在析构函数中删除的指针进行间接操作时,行为也是未定义的。
解决方案:不要使用拥有裸指针。请改用智能指针或容器。std::string
这里似乎合适。
但是为什么首先要创建这个临时对象呢?
因为你String
在print
. 您用 初始化它*this
,因此该对象是一个副本。您不使用返回的对象来初始化变量,因此会物化一个临时对象。
推荐阅读
- regex - 正则表达式匹配特定字符串之前的所有内容(如果存在)(GA Data Studio)
- go - 将浮点结构转换为数组而无需迭代
- javascript - 如何在多个 Google 表格中使用多个 OnEdit 功能
- c# - 能够合并冲突的 Visual Studio 2019 新 Git 体验
- mapbox - Mapbox Directions,自定义路线源
- javascript - 为什么即使我正在处理正在发生的假定错误,我的 nodejs 服务器也会崩溃?
- java - java - 如何从带有数组的csv文件中删除记录
- python - 在 python 中创建自己的 haar 级联模型时出错
- c++ - 使用 R 中的多维数值积分加速 for 循环
- spring - 带有 Spring 缓存和咖啡因的 Spring Cloud Gateway