我在探索丑陋的std::intializer_list世界。
据我所知,从标准来看:
第11.6.4节
因此,如果E类型是一个类,我希望调用复制构造函数。
以下类不允许复制构造:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
};我将尝试用这个类实例化一个std::initializer_list。
#include <vector>
void foo() {
std::vector<NonCopyable>{NonCopyable{}, NonCopyable{}};
}使用g++-8.2 -std=c++14,我得到了我所期望的,编译器错误:
error: use of deleted function 'NonCopyable::NonCopyable(const NonCopyable&)'。
太棒了!
然而,行为随着新标准的变化而变化。
实际上,g++-8.2 -std=c++17编译。
我认为这是因为新标准最初对copy elision提出了新的要求。
但是,更改标准库实现(保持c++17)返回错误:
clang-7 -std=c++17 -stdlib=libc++失败:
'NonCopyable' has been explicitly marked deleted here NonCopyable(const NonCopyable&) = delete;
那我错过了什么?
1) C++17在initializer_list元素的复制构造中是否需要复制?
2)为什么libc++实现没有在这里编译?
编辑请注意,在示例g++ -std=c++17 (编译)中,如果我将默认构造函数更改为“用户定义的”:
struct NonCopyable {
NonCopyable();
NonCopyable(const NonCopyable&) = delete;
};该程序不再编译(不是因为链接错误)。
发布于 2019-02-03 00:05:00
问题是,这种类型:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
};都是可以抄袭的。因此,作为一种优化,由于std::initializer_list只是由一个数组支持,libstdc++所做的只是将整个内容作为一个优化记录到vector中。请注意,即使它有一个已删除的复制构造函数,这种类型也是可以复制的!
这就是为什么当您让用户提供默认构造函数(只编写;而不是= default;)时,突然不再编译了。这使得类型不再是琐碎的可复制的,因此memcpy路径就消失了。
至于这种行为是否正确,我不确定(我怀疑这段代码不能编译吗?)我提交了89164,以防万一)。当然,您希望libstdc++在一些可复制的情况下走上这条路--但也许它需要排除这种情况?在任何情况下,您都可以通过另外删除复制赋值操作符来完成同样的任务(您可能无论如何都想要这样做)--这也会导致类型在复制上是不可复制的。
这没有在C++14中编译,因为您无法构造std::initializer_list -复制初始化,因此需要复制构造函数。但是在保证复制的C++17中,std::initializer_list的构造是很好的。但是,实际构建vector的问题与std::initializer_list完全不同(实际上,这完全是一种“红鲱鱼”)。考虑:
void foo(NonCopyable const* f, NonCopyable const* l) {
std::vector<NonCopyable>(f, l);
}在C++11中编译得很好.至少自gcc 4.9以来。
发布于 2019-02-03 00:02:32
C++17在initializer_list元素的复制构造中是否需要复制?
初始化initializer_list的元素从来不保证使用“复制构造”。它只是执行副本初始化。副本初始化是否调用复制构造函数完全取决于初始化过程中发生了什么。
如果您有一个可从int转换的类型,并且执行Type i = 5;,那就是复制初始化。但是它不会调用复制构造函数;它将调用Type(int)构造函数。
是的,initializer_list引用的数组元素的构造容易受到复制省略的影响。包括C++17的保证省略规则。
尽管如此,不容易受到这些规则影响的是vector本身的初始化。vector必须从initializer_list复制对象,因此它们必须有一个可访问的复制构造函数。编译器/库实现如何设法绕过这一点尚不清楚,但这绝对是不规范的行为。
https://stackoverflow.com/questions/54498610
复制相似问题