首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >类的动态分配

类的动态分配
EN

Stack Overflow用户
提问于 2018-06-09 05:16:51
回答 1查看 2K关注 0票数 1

我有一个关于对象数组分配的问题,问题是:我有一个名为person的类:

代码语言:javascript
复制
class Person {
    char* name;
    int ID;


public:
    Person(char* name = NULL, int ID = 0) :name(name), ID(ID) {};
}

我试着让一组人像这样:

代码语言:javascript
复制
Person *pArr = new Person[size];

然后,我从一个文件中提取数据(char*代表字符串,int代表ID),我使用for循环和构造函数将persons放入循环中,如下所示:

代码语言:javascript
复制
for (int j = 0; j < size3; j++) {
pArr[j] = Person(Name, id);
}

当我完成我的程序后,我想使用析构函数并释放存储在char* name中的已分配字符串,但当我添加析构函数时,它会在循环结束后立即触发,每个正在创建的人都会立即被销毁,我知道可以创建一个指针数组,并分配Person,但在这个赋值中,我应该这样做,有没有一种正确的方法可以在不立即触发析构函数的情况下做到这一点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-09 05:37:19

在这一行上:

代码语言:javascript
复制
pArr[j] = Person(Name, id);

您正在创建一个临时Person对象,然后将其分配给pArr[j]对象。Person没有定义显式的复制赋值运算符,因此编译器会自动为您生成一个运算符,它只是执行从一个对象到另一个对象的逐个成员复制值。

当临时文件超出;的作用域时,它将自动销毁。编译器生成的赋值操作符按原样将name指针复制到pArr[j]对象,因此如果Person具有释放其name的析构函数,则pArr[j]对象将留下一个指向已释放内存的悬空name指针。

您的Person类没有遵循Rule of Three

三大定律(也称为三大定律或三大定律)是C++ (在C++11之前)的一条经验法则,它声称如果一个类定义了以下一项(或多项),它可能应该显式地定义所有三项:

  • destructor
  • copy constructor
  • copy赋值操作符

因为您希望Person有一个释放name的析构函数,所以它还需要一个复制构造函数和一个复制赋值操作符,以便它可以复制name以供析构函数释放,例如:

代码语言:javascript
复制
class Person
{
    char* name;
    int id;

public:
    Person(const char* Name = NULL, int ID = 0)
        : name(new char[std::strlen(Name)+1]), id(ID)
    {
        std::strcpy(name, Name);
    }

    Person(const Person &src)
        : name(new char[std::strlen(src.name)+1]), id(src.id)
    {
        std::strcpy(name, src.name);
    }

    ~Person()
    {
        delete[] name;
    }

    Person& operator=(const Person &rhs)
    {
        if (&rhs != this)
        {
            Person tmp(rhs);

            //std::swap(tmp.name, name);
            char *p = tmp.name;
            tmp.name = name;
            name = p;

            id = tmp.id;
        }
        return *this;
    }
};

现在,回到这一行:

代码语言:javascript
复制
pArr[j] = Person(Name, id);

临时文件将被安全、正确地复制到pArr[j]。只需注意,如果您事先动态分配了Name,那么您现在必须在以后释放它,因为Person会生成它自己的内部副本。

如果您可以将char*更改为std::string,那么您就不必担心编译器会进行默认复制,因为std::string符合三的规则,并且将被正确复制:

代码语言:javascript
复制
class Person
{
    std::string name;
    int id;

public:
    Person(const std::string &name = std::string(), int ID = 0)
        : name(name), id(ID)
    {
    }

    // no explicit copy constructor, destructor, or
    // assignment operator is needed, as compiler-generated
    // defaults will suffice...
};
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50768499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档