簡體   English   中英

std :: string作為成員函數的參數的奇怪行為

[英]Strange behavior of std::string as an argument of a member function

我有一堂課:

class MyClass

{
    char *filename1;
    char *filename2;
public:
    void setFilename1(std::string str)
    {
        filename1 = const_cast<char*>(str.c_str())
    }
    void setFilename2(std::string str))
    {
        filename2 = const_cast<char*>(str.c_str())
    }
    void function()
    {
      // do semthing
    }
    void printFilename1()
    {
      std::cout<<filename1<<std::endl;
    }
}

這是我的主要功能:

MyClass *p = new MyClass();
p->setFilename1("first_string");
p->printFilename1();
p->setFilename2("second_string");
p->printFilename1();

輸出令我非常驚訝:

first_string

second_string

我發誓我的函數MyClass :: setFilename2中沒有錯字,而且我沒有兩次設置filename2變量。

我正在使用g ++編譯器版本4.8.4。 這是我編譯課程的方式:

g++ -g -O -Wall -fPIC -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/home/user/root-6.06.00/include -c myClass.cxx

現在,另一個驚喜:當我更改MyClass :: setFilename函數時:

void setFilename2(char* str))
    {
        filename2 = str;
    }

我得到了我期望的輸出:

first_string

first_string

執行函數MyClass :: function()不會更改任何字符串的值。

那么發生了什么? 這與我對C ++的了解相矛盾。 如果一個函數不引用相同的變量並且彼此無關,那么如何影響另一個函數呢?

我想這可能與編譯器版本或某些編譯器選項有關。 但是我不知道發生了什么。

編輯:您能否向我解釋為什么這段代碼的行為方式如此?

c_str()返回一個指向char數組的指針,只要未修改std::string ,該數組就保持有效; 在您的情況下,您的調用c_str()std::string對象在您的方法返回后會立即銷毀(這是根據字符串文字即時創建的臨時對象),因此您可以有效地存儲指向具有以下內容的內存的指針:被釋放。 當您執行printFileName1時看到新值的事實僅僅是分配器正在回收之前用於另一個字符串的內存位置這一事實的副作用。 就標准而言,這都是未定義的行為(您可以預期會發生悲劇性崩潰)。

正確的方法是將std::string直接存儲在您的類中,它將在MyClass實例的整個生命周期中正確管理自己的內存。

class MyClass
{
    std::string filename1;
    std::string filename2;
public:
    void setFilename1(std::string str)
    {
        filename1 = str;
    }
    void setFilename2(std::string str))
    {
        filename2 = str;
    }
    void function()
    {
      // do semthing
    }
    void printFilename1()
    {
      std::cout<<filename1<<std::endl;
    }
}
MyClass *p;
p->setFilename1("first_string");
p->printFilename1();
p->setFilename2("second_string");
p->printFilename1();

您永遠不會為p指向的內存分配內存,因此您在* p上調用的任何內容都是未定義的行為

我認為這也是錯誤的。

void setFilename1(char* str)
{
    std::string buf = str;
    filename1 = const_cast<char*>(buf.c_str())
}

因為'buf'被刪除超出范圍。

還行吧。

void setFilename1(std::string str)
{
    static std::string buf = str;
    filename1 = const_cast<char*>(buf.c_str())
}

其他方法:

class MyClass
{
    char *filename1;
    char *filename2;
public:
    void setFilename1(std::string& str)
    {
        filename1 = const_cast<char*>(str.c_str())
    }
    void setFilename2(std::string& str))
    {
        filename2 = const_cast<char*>(str.c_str())
    }
    void function()
    {
      // do semthing
    }
    void printFilename1()
    {
      std::cout<<filename1<<std::endl;
    }
}

MyClass *p = new MyClass();
string str1 = "first_string";
p->setFilename1(str1);
p->printFilename1();
string str2 = "second_string";
p->setFilename2(str2);
p->printFilename1();
delete p;

暫無
暫無

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

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