[英]Why copy constructor is called in std::vector's initializer list?
I have the following very simple class: 我有以下非常简单的课程:
class Foo
{
public:
Foo() {}
Foo(const Foo&) = delete;
Foo(Foo&&) {}
void operator=(const Foo&) = delete;
void operator=(Foo&&) {}
void dump() const {}
};
The class is move constructible and assignable but isn't copy constructible and assignable. 该类是可构造和可分配的,但不是可复制的可分配的。
I'd like to initialize a vector of Foo elements using vector's initializer list. 我想使用vector的初始化列表初始化Foo元素的向量。
std::vector<Foo> vf = { Foo() };
The compiler complains because code has to use the deleted copy constructor. 编译器抱怨,因为代码必须使用已删除的复制构造函数。 Could anybody explain, why the move construct is not used in this case, and why copy of the object is needed? 任何人都可以解释一下,为什么在这种情况下不使用移动构造,以及为什么需要复制对象?
The following also requires the copy constructor and does not work either: 以下还需要复制构造函数,但不起作用:
std::vector<Foo> vf = { std::move(Foo()) };
On the other hand, this works fine (the move constructor is called): 另一方面,这工作正常(调用移动构造函数):
std::vector<Foo> vf;
vf.push_back(Foo());
Thanks for the explanation... :) 感谢您的解释... :)
Update: 更新:
A suggested this post explains my question. 建议这篇文章解释我的问题。
Furthermore let's consider the following code (together with class Foo
above): 此外,让我们考虑以下代码(与上面的class Foo
一起):
class Bar {
public:
Bar(std::initializer_list<Foo> _l) {
std::cout << "Bar::Bar()" << std::endl;
for (auto& e : _l)
e.dump();
}
};
int main() {
Bar b { Foo() };
return 0;
}
This produces the following output (compiled with C++11): 这会产生以下输出(使用C ++ 11编译):
Foo::Foo()
Bar::Bar()
Foo::dump()
Foo::~Foo()
It can be seen, that the initializer list is not actually filled with the 'copy of the objects' stated between the braces. 可以看出,初始化列表实际上并没有填充大括号之间声明的“对象副本”。 This might be not true from C++14. 从C ++ 14开始可能不是这样。
It's specifically because you use an initializer list that the copy-constructor is used. 这是因为您使用了使用复制构造函数的初始化列表 。 The initializer list is initialized with a copy of the object, and then passed to the vector. 初始化列表初始化为对象的副本 ,然后传递给向量。
If you read the linked reference, from C++14 it even explicitly say 如果您阅读链接引用,从C ++ 14它甚至明确地说
... each element is copy-initialized ... from the corresponding element of the original initializer list ...每个元素都是从原始初始化列表的相应元素复制初始化的 ....
Emphasis mine 强调我的
std::initializer_list
doesn't work for move-only types. std::initializer_list
不适用于仅移动类型。 See this question for more details. 有关详细信息,请参阅此问题 。
Fortunately, there's a dead easy fix for you: 幸运的是,有一个简单易用的解决方案:
std::vector<foo> vf (1);
This will initialize the vector with 1 default-constructed foo
. 这将使用1个默认构造的foo
初始化向量。
On general the requirements that are imposed on the elements of a std::vector
is that the element type is a complete type and meets the requirements of Erasable. 一般来说,对std::vector
的元素施加的要求是元素类型是完整类型并且满足Erasable的要求。 As such there's no problem with your object. 因此,您的对象没有问题。
However, initializing with an initializer list as such: 但是,使用初始化列表初始化如下:
std::vector<Foo> vf = { Foo() };
Requires that the temporary object Foo()
in the list be copied into the vector. 要求将列表中的临时对象Foo()
复制到向量中。 Consequently, the compiler complains because you've already made your object non-copyable. 因此,编译器会抱怨,因为您已经使对象不可复制。
You can accomplish what you want in the following way; 您可以通过以下方式完成您想要的任务;
std::vector<Foo> vf(1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.