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

时间:2016-11-11 18:06:21

标签: c++ optimization memory-management stack stdstring

我无法理解当文本大小相等时指针是如何相同的。似乎firstStringObj :: 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)\n\n", firstConstCharPointer,firstConstCharPointer, firstStringObj.c_str(),     firstStringObj.c_str()  );
}

输出: firstConstCharPointer(喜+)(0x4593eb8) firstStringObj(您好+)(0x4593eb8)

4 个答案:

答案 0 :(得分:4)

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

这是因为std::string返回的getConstCharAndModifyItWithANewString在分配表达式const char* firstConstCharPointer = ...;后被销毁。

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

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

答案 1 :(得分:4)

您有经典的未定义行为。由于printffirstConstCharPointer会尝试撤销%sfirstConstCharPointer指向已被销毁的数据,因为与此指针的生命周期关联的std::string在分配后停止:

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

答案 2 :(得分:3)

documentation:

中所述
  

从c_str()获得的指针可以通过以下方式无效:

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

所以你使用了无效指针,因为析构函数是一个非const成员函数,并没有在上面列出。

答案 3 :(得分:2)

您的函数返回临时 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)\n\n", firstConstStringObj.c_str(), firstConstStringObj.c_str(), secondStringObj.c_str(), secondStringObj.c_str());
}