C++右值引用shared_ptr和右值引用weak_ptr。

5
std::shared_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}

cout << *test() << endl;

上面的代码可以正常工作。请问有人能告诉我"sdsd"字符串存储在哪里?我原以为它会报错,因为rvalue是一个临时对象。rvalue被复制和存储在哪里?

使用weak_ptr

std::weak_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}

  cout << *test().lock() << endl;

有趣的是,上述代码出现了错误。有什么区别?


1
是的,我对C++还很新。 - claudius
1
谢谢。我正在学习C++和https://en.cppreference.com/。你能帮我理解rvalue shared_ptr存储在哪里吗? - claudius
1
我还缩小了问题的范围,以便更容易回答。 - claudius
2
您问题的字面意思是 weak_ptr 的语义不同:它不被视为引用。这就是 weak_ptr 的全部意义所在。 - Passer By
在第二个版本中,临时shared_ptr的销毁意味着对存储的字符串没有引用,因此它被释放。而在第一个版本中,仍然存在一个引用,即返回值。 - M.M
test()返回后,您会得到一个临时对象。通常情况下,它的生命周期(https://en.cppreference.com/w/cpp/language/lifetime)在计算表达式后结束。'*所有临时对象都将在包含它们创建点的(词法)完整表达式计算的最后一步中被销毁*'. 将test()的结果分配给变量以使生命周期更清晰。在第二个示例中,shared_ptr被传递给了一个weak_ptr,当计算对象的活动使用次数时不计算,当离开test()时,使用计数器变为0 - Sebastian
2个回答

6

std::shared_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}

构造的shared_ptr被返回并作为临时变量存活,足够调用者在超出范围并释放由make_shared分配的string之前使用。

"sdsd" string 存储在由返回的shared_ptrowned拥有的动态存储中。

std::weak_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
} 
shared_ptr没有被返回并且超出了范围,带走了由make_shared分配的string。由于这是唯一存在的shared_ptr的副本,这将使得返回的临时weak_ptr变量连接到一个已过期的share_ptr。如果测试lock的返回值,您会看到它是一个默认构造的持有空指针的shared_ptr

std::weak_ptr::lock文档

test返回后,“sdsd”string没有存储在任何地方。它随着拥有它的shared_ptr超出范围而离开。

1
上面的代码是正确的。请问有人能告诉我“sdsd”字符串存储在哪里吗?我本来以为会出错,因为rvalue是一个临时对象。rvalue被复制和存储在哪里呢?
内存是在调用make_shared时分配的。
有趣的是,上面的代码会出错。有什么区别吗?
不同之处在于对weak_ptr进行lock操作可能会失败,如果不存在至少一个shared_ptr指向该对象。这就是weak_ptr的目的--允许释放对象并仅在它仍然存在时访问它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接