通过智能指针赋值给class个成员
Assignment through smart pointer to class members
我对 C++ 还是很陌生,在探索智能指针时,有一个行为我无法完全理解。
考虑以下简单的 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;
}
};
在主代码中,如果我得到指向实例name
的智能指针并尝试修改它,它不会起作用:
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";
产生:
Before: Mary
Before (through pointer): Mary
After: Mary
After (through pointer): Tracy
显然,mary
的 name
成员没有改变。在单步调试工具时,我发现智能指针指向的地址和成员的实际地址根本不一样。但是,如果我直接获取指向同一个成员的指针并尝试更改它的值,它会起作用:
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";
产生:
Before: Mary
Before (through pointer): Mary
After: Tracy
After (through pointer): Tracy
即使我直接设置一个指向成员的智能指针变量,并通过它改变值,还是不行:
auto directPtr = make_unique<string>(mary.name);
cout << "Before: " << mary.name << "\n";
*directPtr = "Jessica";
cout << "After: " << mary.name << "\n\n";
产生:
Before: Tracy
After: Tracy
使用智能指针指向class成员时是否有一些规范或限制?谢谢。
当你这样做时
return make_unique<string>(this->name);
您没有 return 指向 name
的指针您创建了一个 std::unique_ptr<std::string>
并拥有它自己的 std::string
,它是 name
的副本。它与 name
.
完全分开
您可以创建一个具有空删除器的 unique_ptr
并使用指向 name
的指针构造它,但是当您可以简单地 return name
通过引用来获取它的句柄。
我还想指出您应该使用 member initialization list 来初始化您的 class 成员。您正在做的是在构造函数主体中进行分配,但效率不高。对你来说,这看起来像
Student(int studentID, string gender, string name) : studentID(studentID), gender(std::move(gender)), name(std::move(name)) {}
当你使用你的智能指针时,你每次都创建一个值为name
的智能指针的新实例,所以你的指针永远不会真正引用成员变量[的内存地址] =12=] 但是你创建的副本。在更多注释术语中:
unique_ptr<string> getNameUnique()
{
return make_unique<string>(this->name); //copy the value of name into a new object that is a smart pointer
}
您可以考虑使用 shared_ptr
,如下所示:
class Student {
public:
std::shared_ptr<std::string> name;
//.. other member variables
Student(int studentID, string gender, string name)
{
//same as before except for
this->name = std::make_shared<std::string>(name);
}
shared_ptr<std::string> getNameShared()
{
return this->name;
}
//otherwise the same
};
这会将 name
的值存储在 class 中的智能指针中。然后可以从您的成员函数 return 编辑此 shared_ptr
,并且该 return 值的所有者将拥有指向您的 [=17] 所拥有的相同内存 space 的指针=] 实例。然后,如果您在 class 之外修改此智能指针的内容,您也会在 name
成员变量内观察到该更改。
如果您考虑以下代码,它可能有助于您理解正在发生的事情:
return make_unique<string>(this->name);
相当于:
std::unique_ptr<string> p;
p.reset(new string(this->name));
return p;
我对 C++ 还是很陌生,在探索智能指针时,有一个行为我无法完全理解。
考虑以下简单的 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;
}
};
在主代码中,如果我得到指向实例name
的智能指针并尝试修改它,它不会起作用:
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";
产生:
Before: Mary
Before (through pointer): Mary
After: Mary
After (through pointer): Tracy
显然,mary
的 name
成员没有改变。在单步调试工具时,我发现智能指针指向的地址和成员的实际地址根本不一样。但是,如果我直接获取指向同一个成员的指针并尝试更改它的值,它会起作用:
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";
产生:
Before: Mary
Before (through pointer): Mary
After: Tracy
After (through pointer): Tracy
即使我直接设置一个指向成员的智能指针变量,并通过它改变值,还是不行:
auto directPtr = make_unique<string>(mary.name);
cout << "Before: " << mary.name << "\n";
*directPtr = "Jessica";
cout << "After: " << mary.name << "\n\n";
产生:
Before: Tracy
After: Tracy
使用智能指针指向class成员时是否有一些规范或限制?谢谢。
当你这样做时
return make_unique<string>(this->name);
您没有 return 指向 name
的指针您创建了一个 std::unique_ptr<std::string>
并拥有它自己的 std::string
,它是 name
的副本。它与 name
.
您可以创建一个具有空删除器的 unique_ptr
并使用指向 name
的指针构造它,但是当您可以简单地 return name
通过引用来获取它的句柄。
我还想指出您应该使用 member initialization list 来初始化您的 class 成员。您正在做的是在构造函数主体中进行分配,但效率不高。对你来说,这看起来像
Student(int studentID, string gender, string name) : studentID(studentID), gender(std::move(gender)), name(std::move(name)) {}
当你使用你的智能指针时,你每次都创建一个值为name
的智能指针的新实例,所以你的指针永远不会真正引用成员变量[的内存地址] =12=] 但是你创建的副本。在更多注释术语中:
unique_ptr<string> getNameUnique()
{
return make_unique<string>(this->name); //copy the value of name into a new object that is a smart pointer
}
您可以考虑使用 shared_ptr
,如下所示:
class Student {
public:
std::shared_ptr<std::string> name;
//.. other member variables
Student(int studentID, string gender, string name)
{
//same as before except for
this->name = std::make_shared<std::string>(name);
}
shared_ptr<std::string> getNameShared()
{
return this->name;
}
//otherwise the same
};
这会将 name
的值存储在 class 中的智能指针中。然后可以从您的成员函数 return 编辑此 shared_ptr
,并且该 return 值的所有者将拥有指向您的 [=17] 所拥有的相同内存 space 的指针=] 实例。然后,如果您在 class 之外修改此智能指针的内容,您也会在 name
成员变量内观察到该更改。
如果您考虑以下代码,它可能有助于您理解正在发生的事情:
return make_unique<string>(this->name);
相当于:
std::unique_ptr<string> p;
p.reset(new string(this->name));
return p;