C++:C++如何知道破坏容器内的智能指针?
C++: how does C++ know to destruct smart pointers inside containers?
在 The C++ Programming Language 中,有以下示例(部分
3.2.4).
unique_ptr<Shape> read_shape(istream& is);
void user()
{
vector<unique_ptr<Shape>> v;
while (cin)
v.push_back(read_shape(cin));
draw_all(v);
// call draw() for each element
rotate_all(v,45);
// call rotate(45) for each element
} // all Shapes implicitly destroyed
Stroustrup 试图通过使用 unique_ptrs 来表明这一点,一个
不必手动遍历向量并删除所有
形状。我无法理解为什么这是真的。
我对智能指针的理解是,如果一个智能指针sptr是
分配在堆栈上,类似
std::unique_ptr<Shape> sptr(new Shape());
您不需要在函数末尾对其调用 delete。然而,
从我在上面的例子中可以看出那些智能指针不是
在堆栈上,它们被放入 v 的数据数组中,它位于
堆.
这就是析构函数的用途。您看不到破坏唯一指针的“手动循环”,因为该循环在向量的析构函数中。所有容器都会销毁它们的元素。
unique_ptr
是在栈上还是在堆上并不重要。重要的是它会在其析构函数运行时自动调用目标指针上的delete
。
当 vector
超出范围时,向量的 destructor 运行。这会销毁所有包含的元素(在此过程中调用它们的析构函数),然后释放其堆缓冲区。
当 std::vector
的析构函数运行时,它会为其包含的每个对象调用析构函数。 std::unique_ptr
的析构函数在它包装的指针上调用 delete
/delete[]
,因此所有分配的内存都将被正确清理。
是的,如果你在堆上创建了一些东西,你必须自己删除它。与自动变量(堆栈上的变量,即使标准实际上并不强制要求堆栈的存在)不同,这些对象的生命周期(范围)可以跨越函数 return 边界继续。
然而,这里的vector不在堆上——它实际上是一个自动变量,毫无疑问会存储一些它的信息堆(最有可能是包含向量元素的数组),但变量本身不是。
这意味着,当它从 user()
退出时超出范围时,将调用析构函数。该析构函数足够聪明,可以释放向量本身的 heap-specific 内容, 和 为向量中的每个元素调用析构函数。
当然,销毁这些元素中的每一个都可能导致调用更多的析构函数。如果被破坏的元素之一是智能指针,it 将知道它需要释放它对底层指针的控制,方法是释放它或减少计数以表明它没有对此更感兴趣。
当 std::unique_ptr
本身被销毁或重置时,它会在 object/array 它当前持有指向的指针。
如果std::unique_ptr
是在自动内存中创建的,例如堆栈,当它超出范围时会被销毁。
如果 std::unique_ptr
是在 动态 内存中创建的,例如堆,则在调用 delete
时销毁它。
容器拥有它存储的元素。它知道它的元素是否属于定义析构函数的类型,如果是,那么它将在需要时对每个元素调用该析构函数,例如从容器中删除单个元素时,或者当容器本身被破坏或清除时.
因此,如果您有一个包含 std::unique_ptr
个元素的容器,它们将在适当的时候为您销毁,这反过来又会销毁它们指向的东西。
在 The C++ Programming Language 中,有以下示例(部分 3.2.4).
unique_ptr<Shape> read_shape(istream& is);
void user()
{
vector<unique_ptr<Shape>> v;
while (cin)
v.push_back(read_shape(cin));
draw_all(v);
// call draw() for each element
rotate_all(v,45);
// call rotate(45) for each element
} // all Shapes implicitly destroyed
Stroustrup 试图通过使用 unique_ptrs 来表明这一点,一个 不必手动遍历向量并删除所有 形状。我无法理解为什么这是真的。
我对智能指针的理解是,如果一个智能指针sptr是 分配在堆栈上,类似
std::unique_ptr<Shape> sptr(new Shape());
您不需要在函数末尾对其调用 delete。然而, 从我在上面的例子中可以看出那些智能指针不是 在堆栈上,它们被放入 v 的数据数组中,它位于 堆.
这就是析构函数的用途。您看不到破坏唯一指针的“手动循环”,因为该循环在向量的析构函数中。所有容器都会销毁它们的元素。
unique_ptr
是在栈上还是在堆上并不重要。重要的是它会在其析构函数运行时自动调用目标指针上的delete
。
当 vector
超出范围时,向量的 destructor 运行。这会销毁所有包含的元素(在此过程中调用它们的析构函数),然后释放其堆缓冲区。
当 std::vector
的析构函数运行时,它会为其包含的每个对象调用析构函数。 std::unique_ptr
的析构函数在它包装的指针上调用 delete
/delete[]
,因此所有分配的内存都将被正确清理。
是的,如果你在堆上创建了一些东西,你必须自己删除它。与自动变量(堆栈上的变量,即使标准实际上并不强制要求堆栈的存在)不同,这些对象的生命周期(范围)可以跨越函数 return 边界继续。
然而,这里的vector不在堆上——它实际上是一个自动变量,毫无疑问会存储一些它的信息堆(最有可能是包含向量元素的数组),但变量本身不是。
这意味着,当它从 user()
退出时超出范围时,将调用析构函数。该析构函数足够聪明,可以释放向量本身的 heap-specific 内容, 和 为向量中的每个元素调用析构函数。
当然,销毁这些元素中的每一个都可能导致调用更多的析构函数。如果被破坏的元素之一是智能指针,it 将知道它需要释放它对底层指针的控制,方法是释放它或减少计数以表明它没有对此更感兴趣。
当 std::unique_ptr
本身被销毁或重置时,它会在 object/array 它当前持有指向的指针。
如果std::unique_ptr
是在自动内存中创建的,例如堆栈,当它超出范围时会被销毁。
如果 std::unique_ptr
是在 动态 内存中创建的,例如堆,则在调用 delete
时销毁它。
容器拥有它存储的元素。它知道它的元素是否属于定义析构函数的类型,如果是,那么它将在需要时对每个元素调用该析构函数,例如从容器中删除单个元素时,或者当容器本身被破坏或清除时.
因此,如果您有一个包含 std::unique_ptr
个元素的容器,它们将在适当的时候为您销毁,这反过来又会销毁它们指向的东西。