Std::string::c_str()覆盖函数返回的前一个



我无法理解,当文本大小相等时,指针如何相同。好像firststringgobj::c_str()覆盖了前一个的指针。

#include <iostream>
#include <string>
#include <string>
#include <stdio.h>
std::string getConstCharAndModifyItWithANewString( const char* constchar )
{
    std::string stringAtStack( constchar );
    stringAtStack += "::isModified";
    return stringAtStack;
}
int main()
{
    const char* firstConstCharPointer = getConstCharAndModifyItWithANewString("Hi!").c_str();
    std::string firstStringObj = "Hi+";
    printf(" firstConstCharPointer(%s)(%p)nfirstStringObj(%s)(%p)nn", firstConstCharPointer,firstConstCharPointer, firstStringObj.c_str(),     firstStringObj.c_str()  );
}

输出:firstConstCharPointer(嗨+)(0 x4593eb8)firstStringObj(嗨+)(0 x4593eb8)

指针在您的平台上是相同的,因为firstConstCharPointer是一个悬空指针,它指向已释放的内存。

这是因为getConstCharAndModifyItWithANewString返回的std::string在赋值表达式const char* firstConstCharPointer = ...;之后被破坏了。

所以当你创建一个新的std::string对象时,编译器选择使用与之前的std::string对象相同的内存位置,所以指针是相同的。

例如,在我的平台上,指针是相同的,它们不在Ideone中。

您有典型的未定义行为。printf试图解除firstConstCharPointer的保护,因为%sfirstConstCharPointer指向已经被销毁的数据,因为与此指针相关的std::string在赋值后停止生存期:

const char* firstConstCharPointer = getConstCharAndModifyItWithANewString("Hi!").c_str();
// temporary std::string returned from getConstCharAndModifyItWithANewString destroyed, pointer becomes dangling.

如文档中所述:

从c_str()中获得的指针可能会被以下方式无效:

  • 将字符串的非const引用传递给任何标准库函数,或者
  • 在字符串上调用非const成员函数,不包括操作符[]、at()、front()、back()、begin()、rbegin()、end()和rend()。

因此使用了无效指针,因为析构函数是非const成员函数,上面没有列出。

你的函数返回一个临时 std::string对象。在firstConstCharPointer变量被赋值并且表达式完成之后,该临时对象被销毁,释放其分配的内存块,并使变量指向已释放的内存。这被称为悬空指针

然后

firstStringObj分配一个新的内存块,碰巧重用了临时std::string之前分配和释放的内存块。因此悬空指针恰好现在又指向有效内存。这就是为什么你的printf()语句能够为两个字符串显示相同的内存地址和内容。

但这是未定义行为。每次分配的内存块完全由字符串的Allocator来决定。第二个std::string可以很容易地分配一个完全不同的内存块,然后代码将更有可能崩溃,或者至少打印垃圾,当它试图解引用仍然指向无效内存的悬空指针时。

为了使您的代码工作,您需要将firstConstCharPointer更改为std::string对象,以便正确复制临时std::string,例如:

#include <iostream>
#include <string>
#include <cstdio>
std::string getConstCharAndModifyItWithANewString( const char* constchar )
{
    std::string stringAtStack( constchar );
    stringAtStack += "::isModified";
    return stringAtStack;
}
int main()
{
    const std::string firstConstStringObj = getConstCharAndModifyItWithANewString("Hi!");
    std::string secondStringObj = "Hi!";
    std::printf(" firstConstStringObj(%s)(%p)nsecondStringObj(%s)(%p)nn", firstConstStringObj.c_str(), firstConstStringObj.c_str(), secondStringObj.c_str(), secondStringObj.c_str());
}

相关内容

  • 没有找到相关文章

最新更新