【问题标题】:How do I access the contents of a std::shared_ptr?如何访问 std::shared_ptr 的内容?
【发布时间】:2015-08-23 03:10:23
【问题描述】:

这是我的代码。

std::shared_ptr<WSUStudent> WSUStudent::registerStudent(
   std::string lastName,
   std::string firstName
)
{
   auto result = std::shared_ptr<WSUStudent>(new WSUStudent(lastName, firstName));

   s_allStudents.insert(&result);

   return result;
}

我已经成功地改变了函数,使它返回一个 shared_ptr 而不是一个普通的指针。根据分配(我认为),我已经成功地用共享指针封装了“new”语句,但是“auto”下面的代码行在没有 & 的情况下不起作用,并且在 & 的情况下也不起作用。我收到一条错误消息,指出没有匹配的函数调用,无论是否带有 &。那行代码试图将新学生(或指向新学生的指针?)插入到所有学生的列表中。然而,“插入”方法并没有在本地被覆盖,所以我不太确定在这里做什么。下面打印错误。

/mnt/hgfs/Data Structures and Algorithms/HW04/WSUStudent.cpp:146:32: error: no matching function for call to ‘std::set<WSUStudent*>::insert(std::shared_ptr<WSUStudent>*)’
    s_allStudents.insert(&result);

这个赋值的重点是通过将普通指针转换为弱指针和共享指针来修复内存泄漏(不会被指针删除的“新”语句)。原代码如下。

WSUStudent *WSUStudent::registerStudent(
   std::string lastName,
   std::string firstName
)
{
   auto result = new WSUStudent(lastName, firstName);

   s_allStudents.insert(result);

   return result;
}

我做错了吗?我无法运行 s_allStudents 行。

【问题讨论】:

  • s_allStudents是什么类型?
  • s_allStudents 的声明是 static std::set s_allStudents;我将尝试在等待时将括号中的 WSUStudent * 更改为 shared_ptr。
  • s_allStudents.insert(&amp;result); 不好。您正在存储指向堆栈上对象的指针。
  • 您可以使用 result.get() 来获取 shared_ptr 对象中的指针。
  • 更改声明以使用共享指针解决了问题,但创建了一个新问题。当我修复新错误时,我会更新并回答我自己的问题。它看起来很简单。

标签: c++ pointers c++11 netbeans shared-ptr


【解决方案1】:

给定s_allStudents的类型,你可以使用:

s_allStudents.insert(result.get());

但是,更好的选择是更改 s_allStudents 的类型。

static std::set<std::shared_ptr<WSUStudent>> s_allStudents;

并使用:

s_allStudents.insert(result);

更新

shared_ptr 的默认 operator&lt;() 是这样的,s_allStudents 中的对象将按指针值排序。如果您想使用不同的标准对对象进行排序,您需要定义一个自定义函子/函数作为模板的参数。

struct MyCompare
{
   bool operator<(shared_ptr<WSUStudent> const& lhs,
                  shared_ptr<WSUStudent> const& rhs) const
   {
      // Implement the logic ...
   }
};

并将其用作:

static std::set<std::shared_ptr<WSUStudent>, MyCompare> s_allStudents;

【讨论】:

  • 你不是说std::set&lt;std::shared_ptr&lt;WSUStudent&gt;&gt;吗?
  • OP 说任务是从函数返回一个std::shared_ptr。如果s_allStudents 打算成为对象的owner(看起来很可能),那么将raw pointer 添加到拥有容器之一是危险的。此外,如果您像第二个示例中那样按值存储对象并返回指向这些对象的std::shared_ptr,那么这又是 UB 等待发生。
  • @sjdowling,是的。谢谢你告诉我。
  • 他可能还想在s_allStudents 的模板参数中添加一个比较运算符。目前会按照内存地址排序。
【解决方案2】:

如果您要返回 std::shared_ptr&lt;WSUStudent&gt;,那么您将返回对您创建的对象的所有权权限 - 这意味着其他人将在某个时候尝试将其删除。

除非您也保留所有权,否则您的指针可能会在您完成之前删除。因此,您还需要将std::shared_ptr 存储在您的 static 集中:

我猜你是如何使用这个类的,但我的意思是这样的:

class WSUStudent
{
    // you really need to store shared pointers in here
    static std::set<std::shared_ptr<WSUStudent>> s_allStudents;

    std::string lastName;
    std::string firstName;

    // only the static factory function can make students
    WSUStudent(
        const std::string& lastName, // passing by const& is more usual (idiomatic)
        const std::string& firstName)
    : lastName(lastName)
    , firstName(firstName)
    {
    }

public:

    static std::shared_ptr<WSUStudent> registerStudent(
        const std::string& lastName,
        const std::string& firstName);
};

std::shared_ptr<WSUStudent> WSUStudent::registerStudent(
    const std::string& lastName,
    const std::string& firstName
)
{
    auto result = std::shared_ptr<WSUStudent>(new WSUStudent(lastName, firstName));

    // put the shared student in your set
    s_allStudents.insert(result);

    return result;
}

// define your set
std::set<std::shared_ptr<WSUStudent>> WSUStudent::s_allStudents;

int main ()
{
    // make students
    auto s = WSUStudent::registerStudent("bill", "bob");
    // all deletions should be in order
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 2022-07-10
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 2011-10-29
    相关资源
    最近更新 更多