I'm still quite new to C++, and when I was exploring smart pointers, there was a behavior that I couldn't fully understand.
Consider the following simple class:
class Student {
public:
int studentID;
string gender;
string name;
Student(int studentID, string gender, string name)
{
this->studentID = studentID;
this->gender = std::move(gender);
this->name = std::move(name);
}
unique_ptr<string> getNameUnique()
{
return make_unique<string>(this->name);
}
string* getNamePtr()
{
return &name;
}
};
In the main code, if I get the smart pointer that points to the name
of an instance and try to modify it, it won't work:
auto nameUniquePtr = mary.getNameUnique();
cout << "Before: " << mary.name << "\n";
cout << "Before (through pointer): " << *nameUniquePtr << "\n";
*nameUniquePtr = "Tracy";
cout << "After: " << mary.name << "\n";
cout << "After (through pointer): " << *nameUniquePtr << "\n\n";
produces:
Before: Mary
Before (through pointer): Mary
After: Mary
After (through pointer): Tracy
Apparently, the name
member of mary
wasn't changed. When stepping through the debug tools, I found that the addresses the smart pointer pointed to and the actual address of the member weren't even the same. However, if I directly get the pointer to the same member and try to change the value of it, it works:
auto namePtr = mary.getNamePtr();
cout << "Before: " << mary.name << "\n";
cout << "Before (through pointer): " << *namePtr << "\n";
*namePtr = "Tracy";
cout << "After: " << mary.name << "\n";
cout << "After (through pointer): " << *namePtr << "\n\n";
produces:
Before: Mary
Before (through pointer): Mary
After: Tracy
After (through pointer): Tracy
Even if I directly set a smart pointer variable that points to the member and change the value through it, it still won't work:
auto directPtr = make_unique<string>(mary.name);
cout << "Before: " << mary.name << "\n";
*directPtr = "Jessica";
cout << "After: " << mary.name << "\n\n";
produces:
Before: Tracy
After: Tracy
Are there some specifications or limitations when smart pointers are used to point to class members? Thanks.
When you do
return make_unique<string>(this->name);
You are not returning a pointer to name
You create a std::unique_ptr<std::string>
that holds it's own std::string
that is a copy of name
. it is completely separate from name
.
You could create a unique_ptr
that has a null deleter and construct it with a pointer to name
but that is a lot of work when you could simply return name
by reference to get a handle to it.
I would also like to point out that you should use a member initialization list to initialize your class members. What you are doing is assinging in the constructor body which is not as efficent. For you that would look like
Student(int studentID, string gender, string name) : studentID(studentID), gender(std::move(gender)), name(std::move(name)) {}