std::list 模板在其实例类型中是不是需要复制构造函数(或等效项)?

Posted

技术标签:

【中文标题】std::list 模板在其实例类型中是不是需要复制构造函数(或等效项)?【英文标题】:Does std::list template require a copy constructor (or equivalent) in its instance type?std::list 模板在其实例类型中是否需要复制构造函数(或等效项)? 【发布时间】:2017-06-14 16:02:58 【问题描述】:

我有一个类,每个实例都将被解释,创建和销毁受到严格监管。不允许随机移动、复制、临时 - 一旦通过专用函数创建,实例只能通过引用和指针“传递”。

为此,我删除了该类的复制构造函数和赋值运算符。

这些实例本应保存在 std::list 中,由 emplace_back() 创建,按需删除,并且从未打算移动。但我收到有关已删除的复制构造函数的错误。

 In constructor 'std::_List_node<_Tp>::_List_node(_Args&& ...) 
 error: deleted function 'Reader::Reader(const Reader&) 
          stl_list.h:103: error: used here

有没有办法让这个工作?我不需要手工雕刻的 std::list 的替代品?

【问题讨论】:

你是否保留了移动语义? 哪个版本的标准?哪一行代码导致错误? 添加移动构造函数? 您如何将对象添加到list @MooingDuck: list.emplace_back(params); 【参考方案1】:

标题中问题的答案是“视情况而定”。

如果你的类确实有一个移动构造函数,你将能够使用移动构造函数。如果您的类没有移动构造函数,则将使用复制构造函数。

列表中的对象必须以某种方式构造。 emplace_back 使其尽可能高效,但它仍然需要构造一个对象。来自http://en.cppreference.com/w/cpp/container/list/emplace_back:使用placement-new在容器提供的位置就地构造元素。

emplace_back 的参数是另一个对象时,放置 new 将最终调用复制构造函数或移动构造函数。

如果emplace_back 的参数只是构造对象所需的数据,则不需要复制构造函数或移动构造函数。


有没有办法让它工作?

如果您或您的团队关于复制构造函数和移动构造函数的政策尚未公开讨论,您将不得不使用变通方法。

解决方法 1:

存储指向列表中对象的指针。这是最简单的解决方法,只要您可以确保不会在列表背后删除对象并让列表保持悬空指针。

解决方法 2:

存储列表中对象的非指针句柄。这将需要您编写一些簿记代码。如果您可以添加以下功能:

    在给定对象指针的情况下获取整数值。整数值可以用作对象的非指针句柄。 在给定先前返回的句柄的情况下获取指向对象的指针。

您可以使用句柄列表轻松管理。

上面的内容可以很容易地通过保持几个随着对象的构造和删除而更新的地图来完成。每次创建对象时,都会将条目添加到映射中。每次删除对象时,都会从地图中删除条目。

【讨论】:

我会说我有点困惑为什么std::list首先需要复制或移动ctor——emplace_back()在技术上不能在没有任何东西的情况下在其最终位置创建新对象复制还是移动?这是标准中的疏忽还是std::list 必须能够移动存储在列表中的对象? @cdhowie,列表中的对象必须以某种方式构造。 emplace_back 使其尽可能高效,但仍需要构造一个对象。来自en.cppreference.com/w/cpp/container/list/emplace_back:使用placement-new在容器提供的位置就地构造元素。 对。为什么这需要复制或移动对象?除非 OP 试图将对象移动到列表中。也许 OP 的解决方案应该是从那里开始放置对象?我想这个问题有点不清楚对象是如何构造的。 @cdhowie,当emplace_back 的参数是另一个对象时,放置 new 将最终调用复制构造函数或移动构造函数。 @R Sahu 您是否考虑将关于放置新调用复制/移动构造函数的评论放入答案正文中?那是我完全理解您的答案所需的缺失链接。

以上是关于std::list 模板在其实例类型中是不是需要复制构造函数(或等效项)?的主要内容,如果未能解决你的问题,请参考以下文章

STL源码学习std::list类的类型别名分析

如何使用迭代器擦除 std::list 模板

无法将模板参数传递给 std::list<T>::iterator [重复]

FJUTOJ-3682 LRU算法的实现2 (链表+哈希)

std :: list对其allocator参数做了什么?

多类型模板的诗篇注释