C++ - std::string::~string() 字符串仍然可以打印为空值

C++ - std::string::~string() string can still be printed as a null value

本文关键字:string 打印 空值 std C++ 字符串      更新时间:2023-10-16

当我和std::string一起去的时候,我决定做以下几件事:

int main(int argc, char **argv)
{
    std::string s = "Hello World";
    s.~basic_string();
    std::cout << s.c_str();
}

但是,它什么也不打印,也没有垃圾。但是,在我的basic_string课上,当调用析构函数时,我得到了垃圾。std::string如何处理这个问题?我的使用allocatorconstruct s,destroy s,allocate s和deallocate s,但它仍然不起作用。

注意:我不是在为我的班级寻找解决方案,而是要了解std::string是如何做到的。

首先,你不应该显式调用析构函数,除非在极少数特定情况下,这不是其中之一。当字符串超出范围时,析构函数将按照标准保证自动调用。

其次,在使用被破坏的物体时,除了垃圾之外,你还期待什么?这是应避免的未定义行为。如果要限制范围,请使用大括号,然后创建一个子作用域,并导致调用对象析构函数并清理内容。

int main(int argc, char **argv)
{
    { // new scope
      std::string s = "Hello World";
      std::cout << s;
    } // s destructor called for you
  // other stuff
}

在生存期已结束的对象上调用析构函数是未定义的行为。 std::string有一个不平凡的析构函数,所以当它超出范围时,它的生命周期已经结束。自动调用的析构函数应导致双重释放错误。因为它是未定义的行为,所以没有什么是可以保证的。

显式调用析构函数是否会导致此处未定义的行为?非常详细地介绍了这一点。

虽然这是未定义的行为,因为物体被摧毁了,但我可以猜测幕后发生了什么。

std::basic_string 类型的对象为空时,以下构造 s[0] 有效。对于考试

std::string s;
std::cout << s[0];

在这种情况下,该类返回对初始化为零的 char 类型的对象的引用。因此,该类似乎包含具有值 char(0) 的数据成员。因此,当未分配内存时,即当对象充足时,类返回指向此数据成员的指针,例如调用c_str()

因此,释放早期分配的内存后析构函数似乎将相应的指针设置为 NULL。调用函数 c_str() 时,它会检查指针是否等于 NULL。如果是这样,那么它返回指向我所描述的数据成员的指针。

这可能是您正在寻找的解决方案:)