Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么是独一无二的;T>;(T*)明确?_C++_Pointers_C++11_Type Conversion_Unique Ptr - Fatal编程技术网

C++ 为什么是独一无二的;T>;(T*)明确?

C++ 为什么是独一无二的;T>;(T*)明确?,c++,pointers,c++11,type-conversion,unique-ptr,C++,Pointers,C++11,Type Conversion,Unique Ptr,以下函数不可编译: std::unique_ptr<int> foo() { int* answer = new int(42); return answer; } std::unique_ptr<int> bar() { return new int(42); } std::unique_ptr foo() { 整数*答案=新整数(42); 返回答案; } 标准::唯一的测试条() { 返回新的int(42); } 我觉得这有点不方便。将s

以下函数不可编译:

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

std::unique_ptr<int> bar()
{
    return new int(42);
}
std::unique_ptr foo()
{
整数*答案=新整数(42);
返回答案;
}
标准::唯一的测试条()
{
返回新的int(42);
}

我觉得这有点不方便。将
std::unique_ptr(T*)
显式化的基本原理是什么?

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

以同样的方式考虑指针可能不动态分配:<代码> int x=5;f&x


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

简短回答:

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

长答案:

如果构造函数是隐式的,那么您可以轻松编写这样的代码:

void f(标准::唯一参数)
{
//代码
}//param将在此处被销毁,即当它超出范围时
//它管理的指针也将被销毁。
现在看看危险的部分:

int*ptr=newint;
f(ptr);
//请注意,如果允许,则可以调用f:
//std::unique_ptr test=new int;
//就好像ptr被分配给了参数:
//标准::唯一性测试=ptr;
//危险
*ptr=10//未定义的行为,因为ptr已被唯一的\u ptr删除!
请阅读评论。它解释了上面代码片段的每个部分

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


请注意,
std::shared\u ptr
具有
显式
构造函数的原因与此相同。

的原因与此相同。您真的可以在这样的返回类型中使用
唯一的\u ptr
?这对我来说毫无意义,关键是你不能复制它。@cha0site:它是临时的,所以它是移动的,而不是复制的。@MooingDuck:即使它不是临时的,本地对象在返回语句中也被隐式地当作xvalue处理。+1,尤其是对于“获取所有权是一个非常重要的操作,最好是让它显式。”“获取所有权是一个非常重要的操作,最好是让它显式”这是一个很好的观点。如何降低风险:
void f(int*param){std::unique_ptr smart(param);}
void f(int*param){delete param;}
?@curiousguy:你显然不明白我的答案。
std::unique\u ptr smart(param)
是显式的,而我的回答谈到了从
int*
std::unique\u ptr
的隐式转换所带来的风险。你显然不理解我的评论。显式转换比隐式转换风险小多少?@curiousguy:首先知道“风险”的含义。然后知道“显式”和“隐式”的含义“那么你自己就会明白我的答案了。那么,你认为我不懂“冒险”?
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!