当我和std::string
合作时,我决定做以下事情:
int main(int argc, char **argv)
{
std::string s = "Hello World";
s.~basic_string();
std::cout << s.c_str();
}
然而,它打印没有,并且没有垃圾。但是,在 my basic_string
类中,当调用析构函数时,我会得到垃圾。 std::string
如何处理这个问题?我的使用了allocator
和construct
,destroy
,allocate
和deallocate
,但它仍然不起作用。
注意:我不是在寻找我的类的解决方案,而是要了解std::string
如何做到这一点。
答案 0 :(得分:5)
首先,除非在极少数特定情况下,否则不应显式调用析构函数,这不是其中之一。当字符串超出范围时,将根据标准自动调用析构函数。
其次,在使用被破坏的对象时,您对垃圾的期望是什么?这是应该避免的未定义行为。如果你想限制范围,那么使用花括号然后创建一个子范围,并导致调用对象析构函数和要清理的东西。
int main(int argc, char **argv)
{
{ // new scope
std::string s = "Hello World";
std::cout << s;
} // s destructor called for you
// other stuff
}
答案 1 :(得分:0)
在生命周期结束的对象上调用析构函数是未定义的行为。 std::string
有一个非平凡的析构函数,所以当它超出范围时,它的生命周期已经结束。自动调用的析构函数应该导致双重自由错误。因为它是未定义的行为,所以没有任何保证。
Does explicitly calling destructor result in Undefined Behavior here?详细介绍了这一点。
答案 2 :(得分:-1)
虽然它是未定义的行为,因为对象被破坏但我可以猜出场景背后发生了什么。
当类型std::basic_string
的对象为空时,以下结构s [0]有效。例如
std::string s;
std::cout << s[0];
在这种情况下,该类返回对char类型的对象的引用,该对象初始化为零。所以似乎该类包含具有值char(0)的数据成员。因此,当没有分配内存时,即当对象为ampty时,类例会在调用c_str()
时返回指向此数据成员的指针。
所以似乎释放早期分配的内存后的析构函数将相应的指针设置为NULL。当您调用函数c_str()
时,它会检查指针是否等于NULL。如果是,则返回指向我所描述的数据成员的指针。
它可能是您正在寻找的解决方案。:)