我对C ++还很陌生,当我在探索智能指针时,有一种我无法完全理解的行为。
考虑以下简单类:
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
显然,name
的{{1}}成员未被更改。当单步执行调试工具时,我发现智能指针指向的地址和成员的实际地址甚至不一样。但是,如果我直接获取指向同一成员的指针并尝试更改它的值,则可以正常工作:
mary
产生
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";
当智能指针用于指向班级成员时,是否存在某些规范或限制?感谢。
答案 0 :(得分:3)
当你这样做时
return make_unique<string>(this->name);
您没有返回指向name
的指针您创建了一个std::unique_ptr<std::string>
,其中包含std::string
name
的副本name
。它与unique_ptr
完全分开。
您可以创建一个具有空删除器的name
,并使用指向name
的指针构建它,但是当您只需通过引用返回Student(int studentID, string gender, string name) : studentID(studentID), gender(std::move(gender)), name(std::move(name)) {}
时就可以完成很多工作掌握它。
我还想指出,您应该使用member initialization list初始化您的班级成员。你正在做的是在构造函数体中进行操作,而不是那么高效。对于你看起来像
@RequestMapping("value = "/yourPostEndpoint", method = RequestMethod.POST)
public void postThis(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String relativeGETUrl = url+"/yourGetEndpoint";
String getEndpointResponse = new RestTemplate().getForObject(relativeGETUrl, String.class);
// Do whatever you want to do with the get response
}
答案 1 :(得分:1)
当您使用智能指针时,每次都会创建一个值为name
的智能指针的新实例,因此您的指针实际上永远不会引用成员变量{{1的内存地址但是你创建的副本。在更多带注释的术语中:
name
您可以考虑使用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
,并且该返回值的所有者将具有指向您的shared_ptr
实例拥有的相同内存空间的指针。然后,如果您在类之外修改此智能指针的内容,您将在Student
成员变量中观察到该更改。
答案 2 :(得分:1)
如果您考虑代码,可能有助于您了解正在发生的事情:
return make_unique<string>(this->name);
相当于:
std::unique_ptr<string> p;
p.reset(new string(this->name));
return p;