繁体   English   中英

我可以在没有赋值运算符的类型的向量中可靠地 emplace_back 吗?

[英]Can I reliably emplace_back in a vector of a type that does not have an assignment operator?

我在 GCC、Clang 和 MSVC 中进行了一些测试,发现emplace_back从不在包含的类上调用赋值运算符。 它只在重新分配发生时调用复制或移动构造函数。 标准是否以某种方式保证了这种行为?

用例是我有一些类按顺序存储在一个数字中,这个数字只会随着时间的推移而增长,直到整个向量被破坏。 我很乐意从赋值运算符中清除我的代码。

这些要求记录在 cppreference.com 上。

对于std::vector<T>::emplace_back

类型要求

- T (容器的element类型)必须满足MoveInsertableEmplaceConstructible的要求。

此外, std::vector有一个一般要求,即类型必须是Erasable

EmplaceConstructible要求类型可以使用给定的分配器构造,并提供参数。 由于您使用的是默认分配器std::allocator<T> ,这仅意味着该类型具有带有这些参数的可访问构造函数。

MoveInsertable要求该类型可使用给定的分配器构造,使用类型T的右值。 对于std::allocator这意味着该类型具有可访问的移动构造函数。

Erasable要求该类型可以使用给定的分配器进行破坏。 对于std::allocator这意味着它有一个可访问的析构函数。

就是这样(除了关于完整类型与不完整类型的一些规则)。 没有提及赋值运算符的要求。

但在 C++11 之前,过去类型总是必须是CopyAssignableCopyConstructible 这已经放松了。 现在,除了Erasable之外,要求仅取决于对向量执行的操作。

是的,如果移动构造函数可用(或就地构造),回放将调用移动构造函数:

#include <iostream>
#include <vector> 

struct Pt {
    Pt() = default;
    
    Pt& operator=(Pt const& other) = delete;
    
    Pt(Pt const&) { std::cout << "copy ctor" << std::endl; }
    Pt(Pt&&){ std::cout << "move ctor" << std::endl; }
};

int main(int argc, char *argv[]) 
{
    std::vector<Pt> v;
    
    v.emplace_back(Pt{});
   
    return 0;  
}  

演示

应用于该类型的实际约束是使其成为MoveInsertableEmplaceConstructible

这是cppreferenceemplace_back的评价:

  • T (容器的元素类型)必须满足MoveInsertableEmplaceConstructible的要求。

对于EmplaceConstructible ,要求是std::allocator_traits<A>::construct(m, p, args); 有效。 这是无聊的约束,只对实际放置元素有用。

MoveInsertable似乎是重新分配所需的概念。
对于MoveInsertable ,要求是std::allocator_traits<A>::construct(m, p, rv); 有效,其中rvT类型(即您的类型)的右值表达式。

construct的定义有点令人困惑,但对于大多数意图和目的而言,它似乎只是将参数转发给构造函数。

换句话说,这两个概念似乎证实了对emplace_back的唯一约束是您需要提供:

  • 允许您就地构造的实际构造函数(duh)
  • 重新分配发生时用于重新定位的移动构造函数(如果缺少则复制)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM