通过智能指针赋值给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

显然,maryname 成员没有改变。在单步调试工具时,我发现智能指针指向的地址和成员的实际地址根本不一样。但是,如果我直接获取指向同一个成员的指针并尝试更改它的值,它会起作用:

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;