簡體   English   中英

std :: string :: c_str()覆蓋了函數返回的前一個

[英]std::string::c_str() overwrittes the previous one returned by a function

我不明白當文本大小相等時指針如何相同。 似乎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(Hi +)(0x4593eb8)firstStringObj(Hi +)(0x4593eb8)

指針在您的平台上是相同的,因為firstConstCharPointer是一個懸空的指針,它指向已釋放的內存。

這是因為在賦值表達式const char* firstConstCharPointer = ...;之后, getConstCharAndModifyItWithANewString返回的std::string被銷毀了const char* firstConstCharPointer = ...;

因此,當您創建一個新的std::string對象時,編譯器選擇使用與以前的std::string對象相同的內存位置,因此指針是相同的。

例如,在我的平台上,指針是相同的,並且它們不在Ideone中

您具有經典的不確定行為。 由於%s printf嘗試取消引用firstConstCharPointer firstConstCharPointer指向已被破壞的數據,因為與該指針的生命周期相關聯的std::string在分配后停止:

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

文檔中所述:

從c_str()獲得的指針可能通過以下方式無效:

  • 將對字符串的非常量引用傳遞給任何標准庫函數,或者
  • 在字符串上調用非常量成員函數,但不包括operator [],at(),front(),back(),begin(),rbegin(),end()和rend()。

因此,您使用的指針無效,因為析構函數是一個非常量成員函數,因此未在上面列出。

您的函數返回一個臨時的 std::string對象。 分配firstConstCharPointer變量並完成表達式后,該臨時對象將被銷毀,釋放其分配的內存塊,並使該變量指向已釋放的內存。 這稱為懸空指針

然后firstStringObj分配一個新的內存塊,該內存塊恰好正在重用temp 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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM