在C++编程语言第4版中,有一个向量实现的示例,请参阅消息末尾的相关代码.
uninitialized_move()通过从旧内存区域移动新T对象将其初始化到新内存区域.然后它调用原始T对象上的析构函数,即移动对象.为什么在这种情况下需要析构函数调用?
这是我的不完全理解:移动对象意味着移动对象拥有的资源的所有权被转移到移动对象.移动对象中的剩余部分是一些不需要销毁的内置类型的可能成员,当vector_base b超出范围时(在reserve ()调用之后,它们将被释放)).移动对象中的所有指针都将被置于nullptr或者使用某种机制来删除这些资源上移动对象的所有权以便我们安全,那么为什么在"vector_base b"时调用耗尽对象上的析构函数"在交换完成后,析构函数仍会解除内存的释放?
我理解在必须调用析构函数时需要显式调用析构函数,因为我们有一些东西需要破坏(例如drop元素)但是在vector_base的std :: move + deallocation之后我看不到它的含义.我在网上阅读了一些文本,我看到被移动对象的析构函数调用作为对象生命周期结束的信号(对谁或什么?).
请告诉我,析构函数还有哪些有意义的工作要做?谢谢!
下面的代码片段来自http://www.stroustrup.com/4th_printing3.html
templatevoid vector ::reserve(size_type newalloc) { if (newalloc<=capacity()) return; // never decrease allocation vector_base b {vb.alloc,size(),newalloc-size()}; // get new space uninitialized_move(vb.elem,vb.elem+size(),b.elem); // move elements swap(vb,b); // install new base } // implicitly release old space template Out uninitialized_move(In b, In e, Out oo) { using T = Value_type ; // assume suitably defined type function (_tour4.iteratortraits_, _meta.type.traits_) for (; b!=e; ++b,++oo) { new(static_cast (&*oo)) T{move(*b)}; // move construct b->~T(); // destroy } return oo; }
Dietmar Kühl.. 34
从一个对象移动只意味着移动的对象可能会在它可能会死之前不久捐出它的内脏以生存在另一个活动对象中.但请注意,仅仅因为一个物体捐赠了它的内脏,物体就没死了!事实上,它可能会被另一个捐赠对象复活并生活在该对象的胆量上.
此外,重要的是要了解移动构造或移动分配实际上可以复制!事实上,如果被移动的类型恰好是带有复制构造函数或复制赋值的C++ 11之前的类型,它们将是副本.即使一个类具有移动构造函数或移动赋值,它也可以选择它不能将其内容移动到新对象,例如,因为分配器不匹配.
在任何情况下,从对象移动可能仍然有资源或需要记录统计数据或其他.要摆脱它需要被摧毁的对象.根据类的合同,它可能在移动之后具有已定义的状态,并且可以在没有任何进一步的情况下被用于新的用途.
从一个对象移动只意味着移动的对象可能会在它可能会死之前不久捐出它的内脏以生存在另一个活动对象中.但请注意,仅仅因为一个物体捐赠了它的内脏,物体就没死了!事实上,它可能会被另一个捐赠对象复活并生活在该对象的胆量上.
此外,重要的是要了解移动构造或移动分配实际上可以复制!事实上,如果被移动的类型恰好是带有复制构造函数或复制赋值的C++ 11之前的类型,它们将是副本.即使一个类具有移动构造函数或移动赋值,它也可以选择它不能将其内容移动到新对象,例如,因为分配器不匹配.
在任何情况下,从对象移动可能仍然有资源或需要记录统计数据或其他.要摆脱它需要被摧毁的对象.根据类的合同,它可能在移动之后具有已定义的状态,并且可以在没有任何进一步的情况下被用于新的用途.