【问题标题】:Why is unique_ptr<T>(T*) explicit?为什么 unique_ptr<T>(T*) 是显式的?
【发布时间】:2012-07-07 06:01:06
【问题描述】:

以下函数无法编译:

std::unique_ptr<int> foo()
{
    int* answer = new int(42);
    return answer;
}

std::unique_ptr<int> bar()
{
    return new int(42);
}

我觉得这有点不方便。将std::unique_ptr&lt;T&gt;(T*) 设为显式的理由是什么?

【问题讨论】:

  • 出于同样的原因shared_ptr is explicit
  • 你真的可以在这样的返回类型中使用unique_ptr 吗?这对我来说没有意义,关键是你不能复制它。
  • @cha0site:它是临时的,所以它是移动的,而不是复制的。
  • @MooingDuck :即使它不是临时的,本地对象在 return 语句中也被隐式地视为 xvalues。

标签: c++ pointers c++11 type-conversion unique-ptr


【解决方案1】:

您不希望托管指针隐式地获取原始指针的所有权,因为这可能会导致未定义的行为。考虑一个函数void f( int * ); 和一个调用int * p = new int(5); f(p); delete p;。现在假设有人重构 f 以获取托管指针(任何类型)并且允许隐式转换:void f( std::unique_ptr&lt;int&gt; p ); 如果允许隐式转换,您的代码将编译但会导致未定义的行为。

以同样的方式考虑指针可能甚至不是动态分配的:int x = 5; f( &amp;x );...

获取所有权是一项非常重要的操作,最好明确说明:程序员(而不是编译器)知道是否应该通过智能指针管理资源。

【讨论】:

  • +1,特别是“获取所有权是一项非常重要的操作,最好明确说明。”
  • "获取所有权是一项非常重要的操作,最好明确说明" 好点。
【解决方案2】:

简答:

explicit 构造函数使得编写危险代码变得困难。换句话说,隐式构造函数可以帮助你更轻松地编写危险代码。

长答案:

如果构造函数是 implicit ,那么你可以轻松地编写这样的代码

void f(std::unique_ptr<int> param)
{
     //code

} //param will be destructed here, i.e when it goes out of scope
  //the pointer which it manages will be destructed as well. 

现在看危险的部分:

int *ptr = new int;

f(ptr); 
//note that calling f is allowed if it is allowed:
//std::unique_ptr<int> test = new int;
//it is as if ptr is assigned to the parameter:
//std::unique_ptr<int> test = ptr;

//DANGER
*ptr = 10; //undefined behavior because ptr has been deleted by the unique_ptr!

请阅读 cmets。它解释了上面代码sn-p的每一部分。

当使用原始指针调用f() 时,程序员可能没有意识到f() 的参数类型是std::unique_ptr,它将获得指针的所有权并在超出范围时将delete 它。另一方面,程序员可能使用它,delete 它甚至没有意识到它已被删除!这一切都是由于从原始指针到std::unique_ptr隐式 转换。

请注意,std::shared_ptr 具有 explicit 构造函数,原因完全相同。

【讨论】:

  • 如何降低风险:void f(int *param) { std::unique_ptr&lt;int&gt; smart(param); }void f(int *param) { delete param; }
  • @curiousguy:你显然没听懂我的回答。 std::unique_ptr&lt;int&gt; smart(param);显式,而我的回答是关于从int*std::unique_ptr&lt;int&gt;隐式转换所带来的风险。
  • 你显然没有理解我的评论。显式转换的风险如何低于隐式转换?
  • @curiousguy:先了解“冒险”的含义。然后知道“显式”和“隐式”的含义。那你自己就明白我的回答了。
  • 那么,你以为我不懂“冒险”吗?
猜你喜欢
  • 2015-04-15
  • 1970-01-01
  • 2015-07-23
  • 2015-11-23
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
相关资源
最近更新 更多