簡體   English   中英

從內部使用靜態std :: string的函數返回const char *是否安全?

[英]Is it safe to return a const char * from a function that use a static std::string internally?

我正在查看以下代碼(簡化)並問自己使用此returnMsg函數有多安全:

#include <iostream>

using namespace std;

const char *returnMsg(const char *msg)
{
    static std::string message;

    message = msg;

    return message.c_str();
}

int main(int argc, char *argv[])
{
    const char *msg1 = returnMsg("Hello world");
    printf("msg1 = %p\n", msg1);
    cout << msg1 << endl;

    const char *msg2 = returnMsg("Good bye");
    printf("msg2 = %p\n", msg2);
    cout << msg2 << endl;

    cout << msg1 << endl;

    return 0;
}

輸出是:

msg1 = 0x23a6028
Hello world
msg2 = 0x23a6028
Good bye
Good bye

msg2寫了兩次,這是我所期望的,因為靜態消息變量在程序的生命周期內保留在內存中,並且沒有內存重新分配,因此msg1地址處寫的內容被msg2的新內容msg2

但是,如果msg2的大小較大,則在std::string message變量中存在內部重新分配,輸出為:

msg1 = 0x1cc6028
Hello world
msg2 = 0x1cc6058
Good bye looooooooooooooooooooooooooooooooooooooooong
Hello world

但我想無法保證msg1地址將來不會被重用,因此對msg1內容的新訪問最終可能會顯示出不同且不連貫的內容。

是否需要以不同的方式編寫此函數以使其可以在沒有上述限制的情況下使用它?

從內部使用靜態std :: string的函數返回const char *是否安全?

是的,那是安全的。

但是在指針失效后使用該指針是不安全的,這就是所示程序的作用。 如果重新分配,則在對該函數的連續調用中賦值將使指針無效。 因此,指針在下一次調用函數之前是安全的(這將導致重新分配)。

是否需要以不同的方式編寫此函數以使其可以在沒有上述限制的情況下使用它?

該功能具有所描述的限制,因此當然必須以不同的方式編寫以不具有這些限制。

你的方法的核心問題是你只有一個靜態字符串,但想要存儲多個字符串而不丟棄任何早期字符串。 所以,似乎你需要一大堆靜態字符串:

const char *returnMsg(const char *msg)
{
    static std::forward_list<std::string> messages;
    messages.emplace_front(msg);
    return messages.front().c_str();
}

雖然這可以像你期望的那樣工作,但這很愚蠢。 考慮一下你是否真的想要為執行的其余部分存儲所有字符串。 如果沒有,那么靜態存儲不是解決方案。

上面的代碼導致未定義的行為 只需看看c_str()文檔:

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

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

當您在returnMsg()內第二次調用operator=時, msg1無效並使用它是未定義的行為

暫無
暫無

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

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