【问题标题】:Copy constructor and const复制构造函数和 const
【发布时间】:2020-12-13 13:11:16
【问题描述】:

这是我遇到问题的代码

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*

【问题讨论】:

  • 这不是复制构造函数!并且类型需要完全相同,是的。
  • 如何将这段代码修改成合理的代码?
  • 不要将该指针分配给您内部保存的类成员。您需要为其分配和管理内存以保存指针参数指向的内容的副本。我想这就是这个构造函数的目的。

标签: c++ constructor constants


【解决方案1】:

简短回答:是的。

长答案: const char* str 是指向内存中包含 c 字符串的区域的指针。通过将其标记为const,您表示它可能不会被更改。您正在尝试创建一个指向同一内存区域的新指针,但这个新指针表示该区域可能会被更改,编译器会抱怨这一点(因为原版说这是不允许的)。

请注意,您当前不是将内容复制到字符串(我怀疑您想要),而是将指针复制到字符串。要实际复制字符串,您必须先分配内存,然后再复制内容。或者只使用std::string,它会为您管理所有这些。

【讨论】:

  • int size = 3;常量 int _size = 大小;工作但不是 const char* 和 char*... 这与指针有关吗?
  • @mbae059 它与 c 样式字符串(零终止的字符序列)有关,不幸的是,它们不是固有类型。标准 c++ 使用 std::string 类弥补了这一空白。
  • @mbae059 之所以有效,是因为它复制了一个值;您实例化原始整数的副本。使用指针,您不会复制它所指向的值,因此新指针也需要为 const
  • 这个答案基本上是正确的,但不要陷入认为const char* 指向C 字符串的陷阱。它只是一个指向const char 的指针。它几乎总是使用作为指向 C 字符串的指针,但有时不是。例如,char ch; const char *ptr = &ch'。 +1。
【解决方案2】:

是的,您不能将 const char* 指针(指向常量的指针)分配给 char* 指针(指向非常量的指针),它们不兼容。

如果您不介意您的类按原样指向原始字符数据,那么您可以将 str 成员设为指向 const 的指针:

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

您只需要确保原始字符数据比您的 MyString 对象更有效。

这可能不是您想要的。另一种选择是让你的类复制字符数据到它自己:

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

请务必按照Rule of 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,它会为您处理所有这些细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多