簡體   English   中英

復制構造函數和常量

[英]Copy constructor and const

這是我遇到問題的代碼

class MyString {
    char* str;
public:
    MyString(const char* _str) : str(_str) {}
}

這是來自編譯器的錯誤消息

錯誤:從 'const char*' 到 'char*' 的無效轉換 [-fpermissive]

這是因為strchar*_strconst char*嗎?

副本(我的意思是str(_str) )是否應該是完全相同的類型(關於const )?

我怎樣才能將此代碼修改為合理的代碼? 我想將MyString(const char* _str)保留為const char*

簡短的回答:是的。

長答案: const char* str是指向 memory 中包含 c 字符串的區域的指針。 通過將其標記為const你是說它可能不會被改變。 您正在嘗試創建一個指向同一 memory 區域的新指針,但這個新指針表示該區域可能會更改,編譯器會抱怨這一點(因為原版說這是不允許的)。

請注意,您當前沒有將內容復制到字符串(我懷疑您想要),而是將指針復制到字符串。 要實際復制字符串,您必須首先分配 memory 然后復制內容。 或者只使用std::string代替,它會為您管理所有這些。

是的,您不能將const char*指針(指向 const 的指針)分配給char*指針(指向非 const 的指針),它們不兼容。

如果您不介意您的 class 按原樣指向原始字符數據,那么您可以使str成員成為指向 const 的指針:

class MyString {
    const char* str;
public:
    MyString(const char* _str) : str(_str) {}
};

您只需確保原始字符數據的壽命超過您的MyString object。

這可能不是您想要的。 另一種選擇是讓您的 class 將字符數據復制到自身中:

class MyString {
    char* str = nullptr;
public:
    MyString(const char* _str) {
        if (_str) {
            str = new char[strlen(_str) + 1];
            strcpy(str, _str);
        }
    }
    ...
};

請務必遵循3/5/0 規則來正確管理該副本。 這意味着實現一個析構函數來釋放副本,以及一個復制構造函數和復制賦值運算符來制作數據的副本,以及一個移動構造函數和移動賦值運算符來移動數據:

class MyString {
    char* str = nullptr;
public:
    MyString() = default;

    MyString(const char* _str) {
        if (_str) {
            str = new char[strlen(_str) + 1];
            strcpy(str, _str);
        }
    }

    MyString(const MyString &src) : MyString(src.str) { }

    MyString(MyString &&src) {
        str = src.str;
        src.str = nullptr;
    }

    ~MyString() {
        delete[] str;
    }

    MyString& operator=(MyString rhs) {
        MyString tmp(std::move(rhs));
        std::swap(src, tmp.src);
        return *this;
    }
};

更好的解決方案是改用std::string ,它會為您處理所有這些細節。

暫無
暫無

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

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