C++ 无效指针的cpp make_共享

C++ 无效指针的cpp make_共享,c++,c++11,smart-pointers,C++,C++11,Smart Pointers,我想使用std::make_shared创建一个空指针。由于make_shared应该比shared_ptr(new T)和exception save更快,我想知道是否有一个库函数以make_shared的方式创建一个shared_ptr(new foo)。你可以将任何shared_ptr转换为shared_ptr,而不会损失make_shared的效率: #include <memory> struct foo {}; int main() { std::shared

我想使用std::make_shared创建一个空指针。由于make_shared应该比shared_ptr(new T)和exception save更快,我想知道是否有一个库函数以make_shared的方式创建一个shared_ptr(new foo)。你可以将任何
shared_ptr
转换为
shared_ptr
,而不会损失
make_shared
的效率:

#include <memory>

struct foo {};

int main()
{
    std::shared_ptr<void> p = std::make_shared<foo>();
}
p1
指向包含引用计数(实际上是两个引用计数:一个用于强所有者,一个用于弱所有者)、删除器、分配器和指向对象“动态”类型的指针的控制块。“动态”类型是
共享\u ptr
构造函数看到的对象的类型,例如
Y
(可能与
T
相同,也可能不同)

p2
具有类型
T*
,其中
T
shared\u ptr
中的
T
相同。将其视为存储对象的“静态”类型。当您解除对
共享\u ptr
的引用时,解除引用的是
p2
。销毁
共享\u ptr
时,如果引用计数变为零,则控制块中的指针有助于销毁
foo

在上图中,控制块和
foo
都是动态分配的<代码>p1是一个拥有指针,控制块中的指针是一个拥有指针<代码>p2是一个非所有者指针
p2
功能仅为解引用(箭头运算符、
get()
等)

使用
make_shared()
时,实现有机会将
foo
与参考计数和其他数据一起放在控制块中:

p1  ---------> (refcount, foo)
p2  --- foo* --------------^
这里的优化是现在只有一个分配:现在嵌入
foo
的控制块

当上述内容转换为
共享\u ptr
时,所发生的一切是:

p1  ---------> (refcount, foo)
p2  --- void* -------------^
也就是说,
p2
的类型从
foo*
变为
void*
。就这样。(除了增加/减少引用计数以说明临时文件的副本和销毁之外——这可以通过从右值中构造而忽略)。当参考计数变为零时,仍然是控制块销毁通过
p1
找到的
foo
<代码>p2不参与销毁操作

p1
实际上指向控制块的通用基类。此基类不知道派生控制块中存储的类型
foo
。当实际对象类型
Y
已知时,派生控制块在
shared_ptr
的构造函数中构造。但是从那时起,
shared\u ptr
只能通过
control\u block\u base*
与控制块通信。因此,破坏之类的事情是通过虚拟函数调用发生的

在C++11中,从右值
共享ptr
共享ptr
的“移动构造”只需复制两个内部指针,而不必操纵引用计数。这是因为rvalue
shared\u ptr
无论如何都将消失:

// shared_ptr<foo> constructed and destructed within this statement
std::shared_ptr<void> p = std::make_shared<foo>();

在转换构造之前,引用计数仅为1。在转换构造之后,引用计数仍然是1,源在其析构函数运行之前指向nothing。简而言之,这就是移动语义的乐趣所在!:-)

您可以将任何
shared_ptr
转换为
shared_ptr
,而不会损失与
make_shared
相关的效率:

#include <memory>

struct foo {};

int main()
{
    std::shared_ptr<void> p = std::make_shared<foo>();
}
p1
指向包含引用计数(实际上是两个引用计数:一个用于强所有者,一个用于弱所有者)、删除器、分配器和指向对象“动态”类型的指针的控制块。“动态”类型是
共享\u ptr
构造函数看到的对象的类型,例如
Y
(可能与
T
相同,也可能不同)

p2
具有类型
T*
,其中
T
shared\u ptr
中的
T
相同。将其视为存储对象的“静态”类型。当您解除对
共享\u ptr
的引用时,解除引用的是
p2
。销毁
共享\u ptr
时,如果引用计数变为零,则控制块中的指针有助于销毁
foo

在上图中,控制块和
foo
都是动态分配的<代码>p1是一个拥有指针,控制块中的指针是一个拥有指针<代码>p2是一个非所有者指针
p2
功能仅为解引用(箭头运算符、
get()
等)

使用
make_shared()
时,实现有机会将
foo
与参考计数和其他数据一起放在控制块中:

p1  ---------> (refcount, foo)
p2  --- foo* --------------^
这里的优化是现在只有一个分配:现在嵌入
foo
的控制块

当上述内容转换为
共享\u ptr
时,所发生的一切是:

p1  ---------> (refcount, foo)
p2  --- void* -------------^
也就是说,
p2
的类型从
foo*
变为
void*
。就这样。(除了增加/减少引用计数以说明临时文件的副本和销毁之外——这可以通过从右值中构造而忽略)。当参考计数变为零时,仍然是控制块销毁通过
p1
找到的
foo
<代码>p2不参与销毁操作

p1
实际上指向控制块的通用基类。这个基类不知道类型
foo<