C++ 为什么';t共享ptr允许直接分配
因此,当使用C++ 为什么';t共享ptr允许直接分配,c++,c++11,shared-ptr,smart-pointers,C++,C++11,Shared Ptr,Smart Pointers,因此,当使用shared\u ptr时,您可以编写: shared_ptr<Type> var(new Type()); 我习惯了OpenCV Ptr类,它是一个智能指针,允许直接赋值,一切正常 为什么[不]shared_ptr允许直接分配[复制初始化] 由于它是显式的,请参见和 我想知道这背后的理由是什么?(摘自现已删除的评论) TL;DR,使任何构造函数(或cast)显式是为了防止它参与隐式转换序列 explicit的要求最好用shared\u ptr作为函数的参数来说明 vo
shared\u ptr
时,您可以编写:
shared_ptr<Type> var(new Type());
我习惯了OpenCV Ptr类,它是一个智能指针,允许直接赋值,一切正常
为什么[不]shared_ptr
允许直接分配[复制初始化]
由于它是显式的,请参见和
我想知道这背后的理由是什么?(摘自现已删除的评论)
TL;DR,使任何构造函数(或cast)显式
是为了防止它参与隐式转换序列
explicit
的要求最好用shared\u ptr
作为函数的参数来说明
void func(std::shared_ptr<Type> arg)
{
//...
}
这将编译,并作为书面和不希望的和错误的;它不会像预期的那样运行
将用户定义(隐式)转换(强制转换运算符)添加到混合中会使问题变得更加复杂
struct Type {
};
struct Type2 {
operator Type*() const { return nullptr; }
};
然后将编译以下函数(如果不是显式的),但提供了一个可怕的错误
Type2 a;
func(a);
允许这样做可以让您直接调用带有指针参数的函数,这很容易出错,因为您在调用站点不一定知道您正在使用它创建共享指针
void f(std::shared_ptr<int> arg);
int a;
f(&a); // bug
void f(标准::共享参数);
INTA;
f(a);//缺陷
即使您忽略了这一点,您也会在呼叫站点创建不可见的临时文件,并且创建共享\u ptr
非常昂贵。语法:
shared_ptr<Type> var = new Type();
允许将原始指针隐式转换为
std::shared_ptr
的问题可以通过
void foo(std::shared_ptr<int> bar) { /*do something, doesn't matter what*/ }
int main()
{
int * bar = new int(10);
foo(bar);
std::cout << *bar;
}
void foo(std::sharedptrbar){/*做点什么,不管做什么*/}
int main()
{
整型*条形=新整型(10);
富(巴);;
标准::cout
我想知道为什么他们不允许一个更简单更好的
随着您的经验越来越丰富,遇到的代码也越来越糟糕,您的观点也会改变
shared_ptr
,与所有标准库对象一样,其编写方式使其尽可能难以导致未定义的行为(即难以找到浪费每个人时间并破坏我们生存意志的bug)
考虑:
#include<memory>
struct Foo {};
void do_something(std::shared_ptr<Foo> pfoo)
{
// ... some things
}
int main()
{
auto p = std::make_shared<Foo>(/* args */);
do_something(p.get());
p.reset(); // BOOM!
}
#包括
结构Foo{};
void do__something(std::shared_ptr pfoo)
{
//…有些事情
}
int main()
{
自动p=std::使_共享(/*args*/);
做某事(p.get());
p、 重置();//轰!
}
这段代码无法编译,这是一件好事。因为如果它编译了,程序将显示未定义的行为
这是因为我们将删除同一个Foo两次
此程序将编译,并且格式良好
#include<memory>
struct Foo {};
void do_something(std::shared_ptr<Foo> pfoo)
{
// ... some things
}
int main()
{
auto p = std::make_shared<Foo>(/* args */);
do_something(p);
p.reset(); // OK
}
#包括
结构Foo{};
void do__something(std::shared_ptr pfoo)
{
//…有些事情
}
int main()
{
自动p=std::使_共享(/*args*/);
做某事(p);
p、 reset();//确定
}
因为std::shared\u ptr
的构造函数获取指针是显式的
,并且没有操作符获取指针。这不是一个赋值。除非你不使用new
创建它,否则你将删除内存,而你没有new
ed.@giò制作一个shared_ptr
比大多数人希望的隐式转换要昂贵得多。对于其他类,它也可能是一个不明显的转换。例如,传递5
并将其转换为std::vector
将非常不直观。@giò这确实是一个大问题。@giò共享指针假定它拥有它是指针(并且只与其他共享指针共享)。如果您将原始指针传递给共享指针,则很可能另一段代码假定它拥有原始指针,并试图在某个点删除它。但是共享指针也会这样做!所以,是的,双重删除根本不好。
auto var = std::make_shared<Type>();
void foo(std::shared_ptr<int> bar) { /*do something, doesn't matter what*/ }
int main()
{
int * bar = new int(10);
foo(bar);
std::cout << *bar;
}
#include<memory>
struct Foo {};
void do_something(std::shared_ptr<Foo> pfoo)
{
// ... some things
}
int main()
{
auto p = std::make_shared<Foo>(/* args */);
do_something(p.get());
p.reset(); // BOOM!
}
#include<memory>
struct Foo {};
void do_something(std::shared_ptr<Foo> pfoo)
{
// ... some things
}
int main()
{
auto p = std::make_shared<Foo>(/* args */);
do_something(p);
p.reset(); // OK
}