The question is how to correctly delete name in A destructor?
class A{
private:
char *name;
public:
A(char *n) : name(n) {}
~A(){
//???
}
}
int main(){
A *a = new A("name");
delete a;
return 0;
}
The question is how to correctly delete name in A destructor?
class A{
private:
char *name;
public:
A(char *n) : name(n) {}
~A(){
//???
}
}
int main(){
A *a = new A("name");
delete a;
return 0;
}
Given that you do not change the constructor, then the correct way is to not delete anything. Ownership of the string belongs to the client, since you are not creating a copy.
However, the right way of rewriting this is to let the constructor allocate a copy of the string with new[]
and let the destructor deallocate it with delete[]
.
And the really right way is to let std::string
do the whole thing for you, and not write an explicit destructor at all:
#include <string>
class A{
private:
std::string name;
public:
A(std::string n) : name(std::move(n)) {}
};
This, by the way, allows you not to worry about the Rule of Three, which means you won't have to bother writing a copy constructor, a move constructor, a copy assignment operator, a move assignment operator, a destructor and whatnot.
You are not allowed to delete a pointer to string constant "name"
.
As your class does not own any objects or memory blocks, it should not delete anything.
In this example you don't need to delete name. "name" is just a pointer to some some place in executable image, not memory allocated with new/malloc/something_else.
"name" occupies static memory that the compiler automatically sets aside. If you delete that memory, the behavior is undefined (i.e. crash). You only 'delete' memory that you 'new' in the first place.
The simplest thing is to use proper C++ (std::string
) and avoid naked pointers, as that simplifies management of resources.
The problem with your interface is that the type A
claims ownership of the argument, but you cannot claim ownership of a string literal, as those are managed by the implementation. You could go on trying to decide whether the caller should create deep copy and pass it to a A
or if A
design should be changed not to attempt to claim ownership and make a copy out of that. But the fact is that things are much simpler if you just use higher level constructs:
class A {
std::string name;
public:
A(const std::string& name) : name(name) {}
};
No need to manually copy data around, no need for a destructor or a copy constructor... all works out of the box.