The problem this: at the end of this function, the members of the element at “tasks[taskCount]” like name, due date, etc, are indeed what was passed into this function, but after returning to this function’s caller, all those values become garbage, except taskcount, which is not dynamic. This function is defined within the scope of class, “Tasklist”
void addTask(char name[],char course[],char dueDate[]){
taskCount++;
Task task(taskCount, name, course, dueDate);
tasks[taskCount] = task;
}
Here is the brief definition for class “Task”:
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;
}
};
I’m pretty sure what is happening is that this function is disposing of its locally declared variable “task” after returning to the caller, which invokes task’s destructor
thereby deallocating the memory that the “tasks” array was referencing for each of it’s element’s members (name, due, course).
So, how do I prevent this from happening?
So by the advice of the many helpful people on this site, I now have this in my Task class definition:
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);
}
So this should account for one of the rule of three, right?
You should use
std::stringinstead ofchar *and let C++ handle allocation for you. No need to calloperator new[],strcpy(), oroperator delete[]when these operations have a better interface in the form ofstd::string.If you cannot use
std::string, then you need to implement a copy constructor forTaskthat takes aconst Task&as its only argument, and an assignment operator that does roughly the same thing. This constructor will then be implicitly used by your code when copying aTaskobject into an array or other place:(These two members tend to have very similar implementations. Factoring out the common code is an exercise for the reader.)