C++动态内存

Col*_*Nye 2 c++ memory pointers dynamic

问题是:在这个函数结束时,"tasks [taskCount]"元素的成员,如名称,截止日期等,确实是传递给这个函数的,但是在返回到这个函数的调用者之后,所有这些值变为垃圾,但taskcount除外,它不是动态的.此函数在类"Tasklist"的范围内定义

void addTask(char name[],char course[],char dueDate[]){
    taskCount++;
    Task task(taskCount, name, course, dueDate);
    tasks[taskCount] = task;
}
Run Code Online (Sandbox Code Playgroud)

以下是"任务"类的简要定义:

class Task
{
private:
    int number;
    char* name;
    char* dueDate;
    char* course;
public:
    Task(){
        name = new char[TEXT_SIZE + 1];
        dueDate = new char[TEXT_SIZE + 1];
        course = new char[TEXT_SIZE + 1];
        saveText = new char[(TEXT_SIZE * 3) + 1];
    };

    Task(int num, char n[], char c[], char d[]){
        number = num;
        name = new char[strlen(n) + 1];
        dueDate = new char[strlen(d) + 1];
        course = new char[strlen(c) + 1];

        strcpy(name, n);
        strcpy(dueDate, d);
        strcpy(course, c);
    };

    ~Task(){
        delete [] name;
        delete [] dueDate;
        delete [] course;
        delete [] saveText;
    }
};
Run Code Online (Sandbox Code Playgroud)

我很确定发生了什么,这个函数在返回调用者之后处理其本地声明的变量"task",调用者调用任务的析构函数,从而释放"tasks"数组为每个元素的成员引用的内存. (姓名,截止日期).

那么,我该如何防止这种情况发生呢?

所以通过本网站上许多有用的人的建议,我现在在我的Task类定义中有这个:

Task(const Task& t){
    name = new char[TEXT_SIZE + 1];
    dueDate = new char[TEXT_SIZE + 1];
    course = new char[TEXT_SIZE + 1];
    saveText = new char[(TEXT_SIZE * 3) + 1];

    number = t.number;
    strcpy(name, t.name);
    strcpy(dueDate, t.dueDate);
    strcpy(course, t.course);
    strcpy(saveText, t.saveText);
}
Run Code Online (Sandbox Code Playgroud)

所以这应该是三个规则中的一个,对吧?

Lig*_*ica 6

您没有编写为您的类型提供正确深度复制语义的复制构造函数,从而违反了三条规则Task.


Kar*_*ath 5

你有没有过度重载复制构造函数和赋值运算符?

您必须创建这些字符串的新副本.


Jon*_*pan 5

您应该使用std::string而不是char *让C++为您处理分配.无需调用operator new[],strcpy()或者operator delete[]当这些操作具有更好的界面时std::string.

如果你不能使用std::string,那么你需要实现一个复制构造函数Task,它将一个const Task&as作为唯一的参数,并且赋值操作符执行大致相同的操作.在将Task对象复制到数组或其他位置时,代码将隐式使用此构造函数:

Task::Task(const Task& t) {
    ...
}

Task& Task::operator =(const Task& t) {
    if (this != &t) {
        ...
    }
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

(这两个成员往往具有非常相似的实现.分解公共代码是读者的练习.)