【问题标题】:Default Constructor Parameter Error - 'Autoturism::Autoturism(char *,unsigned int)': cannot convert argument 1 from 'const char [6]' to 'char *'默认构造函数参数错误 - 'Autoturism::Autoturism(char *,unsigned int)':无法将参数 1 从 'const char [6]' 转换为 'char *'
【发布时间】:2021-10-26 19:17:53
【问题描述】:

一种解决方案是使用(char*)"Rosie" 转换为char*,我很好奇它是否是另一个。

【问题讨论】:

标签: c++ oop memory-leaks string-literals default-arguments


【解决方案1】:

首先,请注意,您的默认参数值 (c = new char[1]()) 是内存泄漏,因为构造函数稍后不会将 new[]'ed 内存的所有权交给delete[]。使用new[]'ed 内存作为参数的默认值从来都不是很好的理由。

"Rosie" 是一个字符串文字。它的类型为 const char[6],在 C++11 及更高版本中不能按原样分配给非 const char* 指针,需要显式类型转换(其中在这种情况下,您应该使用 const_cast 而不是 C 风格的演员表),例如:

#include <iostream>
#include <string>

class Autoturism
{
    static int nr_autoturisme; // nr_autoturis 'active'
    char* culoare;
    unsigned int a_fabricatie;
    
public:
    Autoturism(char* = nullptr, unsigned int = 0);
    ~Autoturism();

    // TODO: you will also need a copy constructor and a
    // copy assignment operator, per the Rule of 3/5/0:
    // https://en.cppreference.com/w/cpp/language/rule_of_three
    ...
};

int Autoturism::nr_autoturisme{ 0 };

Autoturism::Autoturism(char* c, unsigned int an)
{
    if (!c) c = const_cast<char*>("");

    size_t len = strlen(c);
    culoare = new char[len + 1];
    strcpy_s(culoare, len + 1, c);

    an_fabricatie = an;
    ++nr_autoturism;    

    std::cout << "\nConstructorul a fost apelat !";
}

Autoturism::~Autoturism()
{
    delete[] culoare;

    std::cout << "\nDeconstructorul a fost apelat !";
}

...

int main()
{
    Autoturism a1;
    Autoturism a2(const_cast<char*>("Rosie"), 1999);

    ...

    return 0;
}

否则,如果您真的打算继续使用 C 风格的字符串处理,那么您应该c 参数改为const char*(无论如何它应该是pointer-to-const,因为构造函数不会修改指向的数据),例如:

#include <iostream>
#include <string>

class Autoturism
{
    static int nr_autoturisme; // nr_autoturis 'active'
    char* culoare;
    unsigned int a_fabricatie;
    
public:
    Autoturism(const char* = "", unsigned int = 0);
    ~Autoturism();

    // TODO: you will also need a copy constructor and a
    // copy assignment operator, per the Rule of 3/5/0:
    // https://en.cppreference.com/w/cpp/language/rule_of_three
    ...
};

int Autoturism::nr_autoturisme{ 0 };

Autoturism::Autoturism(const char* c, unsigned int an)
{
    if (!c) c = "";

    size_t len = strlen(c);
    culoare = new char[len + 1];
    strcpy_s(culoare, len + 1, c);

    an_fabricatie = an;
    ++nr_autoturism;    

    std::cout << "\nConstructorul a fost apelat !";
}

Autoturism::~Autoturism()
{
    delete[] culoare;

    std::cout << "\nDeconstructorul a fost apelat !";
}

...

int main()
{
    Autoturism a1;
    Autoturism a2("Rosie", 1999);

    ...

    return 0;
}

但是,话虽如此,你为什么要在 C++ 中使用这种旧的 C 风格的字符串处理呢?您应该改用std::string(您已经包含&lt;string&gt; 标头),让它为您处理所有内存管理,例如:

#include <iostream>
#include <string>

class Autoturism
{
    static int nr_autoturisme; // nr_autoturis 'active'
    std::string culoare;
    unsigned int a_fabricatie;
    
public:
    Autoturism(const std::string & = "", unsigned int = 0);

    // std:string is already compliant with the Rule of 3/5/0,
    // so the compiler's auto-generated destructor, copy constructor,
    // and copy assignment operator will suffice...
};

int Autoturism::nr_autoturisme{ 0 };

Autoturism::Autoturism(const std::string &c, unsigned int an)
{
    culoare = c;
    an_fabricatie = an;
    ++nr_autoturism;    

    std::cout << "\nConstructorul a fost apelat !";
}

int main()
{
    Autoturism a1;
    Autoturism a2("Rosie", 1999);

    ...

    return 0;
}

【讨论】:

  • 我喜欢 c++ 风格而不是 c 风格,但这是一个家庭作业,我必须使用 char* 变量(
  • @Dragoş-GeorgeGherasim 那么这是一个非常糟糕的家庭作业。它没有教你良好的 C++ 习惯。
  • 我应该对默认构造函数进行什么更改以避免内存泄漏?
  • @Dragoş-GeorgeGherasim 我已经更新了我的示例来证明这一点。
【解决方案2】:

C++ 中的字符串字面量具有用作表达式的常量字符数组类型,极少数例外被转换为指向它们的第一个字符const char * 类型的指针。但是构造函数的第一个参数的类型是 char * 而不是 const char *。所以编译器会报错。

由于默认参数动态分配内存但未删除,构造函数也可能产生内存泄漏。

您至少可以通过以下方式声明构造函数

Autoturism( const char * = "", unsigned int = 0 );

由于内存是动态分配的,您需要明确定义将删除分配的内存的析构函数以及复制构造函数和复制赋值运算符,或者将最后两个定义为已删除。

【讨论】:

  • @Dragoş-GeorgeGherasim 完全没有。不客气。:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 2015-08-05
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
相关资源
最近更新 更多