【问题标题】:How to use a unique_ptr after passing it to a function?将 unique_ptr 传递给函数后如何使用它?
【发布时间】:2019-09-27 19:31:52
【问题描述】:

我刚开始学习新的 C++ 内存模型:

#include <string>
#include <iostream>
#include <memory>

void print(unique_ptr<std::string> s) {
        std::cout << *s << " " <<  s->size() << "\n";
}

int main() {
        auto s = std::make_unique<std::string>("Hello");
        print(std::move(s));
        std::cout << *s;
        return 0;
}

现在调用cout &lt;&lt; *s; 会导致段错误,这是应该的。我明白为什么会这样。但我也想知道是否有办法取回所有权。我希望能够在将值传递给函数后使用它。

【问题讨论】:

  • 如果你std::move它,那么你就是在放弃它。如果您想保留它,请不要使用std::move。通过引用传递。
  • ^ 话虽如此,即使您决定转让s 的所有权,std::move 也可能不是最好的方法。看看文档中unique_ptr的方法
  • 没有“应该导致段错误”的代码。像这样的不正确代码被描述为具有未定义的行为,这意味着标准不保证一个体面的编译器应该做什么。所以它可能会打印“(null)”,可能什么都不做,可能会给你鼻守护进程。 (也许一旦您开始将目光从标准转向特定的编译器和架构,但随后您会大量依赖于优化选择,而这些选择经常会发生变化。)
  • a) unique_ptr&lt;string&gt; 作为参数的意思是:我会把这个字符串转给你。作为函数的参数,这几乎不是您想要的。你不应该使用unique_ptr 作为参数,除非真的需要。 b) 使用引用,如果您不修改它,则使用 const 引用。 const string&amp; 的意思是:我会给你一个存在的字符串(引用不能为空,不需要空检查)它是我的(所有权仍然在调用者身上) 并且您不应该修改它。 string&amp; 表示:它是我的,但你可以触摸。 c) 可以为空的标准指针(即可选参数)。
  • @aschepler 特定平台 (POSIX) 确实定义了导致段错误的某些事情。 (虽然我实际上并没有检查过 POSIX 标准)

标签: c++ unique-ptr


【解决方案1】:

如果您不想转移拥有对象的所有权,则不要将unique_ptr 传递给函数。相反,将引用或原始指针传递给函数(在现代 C++ 风格中,原始指针通常被理解为非拥有指针)。如果您只想读取对象,则 const 引用通常是合适的:

void print(const std::string&);
// ...
print(*s);

【讨论】:

  • 我明白了,谢谢。但我读到我应该对所有内容使用唯一指针。这有效:void print(unique_ptr&lt;string&gt; &amp;s)。那么我什么时候应该使用unique_ptr&lt;string&gt; vs unique_ptr&lt;string&gt;&amp; vs string&amp;
  • @Alex 你不应该在任何地方都使用unique_ptr。您应该确保每个动态分配的资源都由一个 RAII 对象拥有,例如unique_ptr 或一个容器,当它超出范围时将释放它。如果您有一个由 unique_ptr 拥有的对象,那么可以通过原始指针或引用来“观察”它。
  • @Alex 一些术语方面的帮助:What is ownership of resources or pointers?
猜你喜欢
  • 2012-03-30
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 2014-11-09
  • 2018-03-12
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多