简体   繁体   English

为什么在std :: vector的初始化列表中调用复制构造函数?

[英]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.

相关问题 为什么 std::vector 构造函数通过复制接受初始化列表? - Why does the std::vector constructor accept initializer list by copy? 为什么在此示例中使用 std::vector 调用复制构造函数? - Why is the copy constructor called in this example with std::vector? std::vector 中的初始化列表构造函数 - initializer list constructor in std::vector 为什么在调用std :: vector :: emplace_back()时调用复制构造函数? - Why is copy constructor called in call to std::vector::emplace_back()? 返回std :: vector时未调用复制构造函数 - copy constructor not called when returning a std::vector 在类的初始化器列表中初始化std :: vector - Initialize std::vector in class's initializer list 我打算调用initializer_list构造函数,如果存在,则预先调用复制构造函数:为什么? - I intend to call initializer_list constructor, and copy constructor is called beforehand if it exists: why? 复制构造函数与 std::initializer_list 构造函数 - Copy constructor vs std::initializer_list constructor 为什么调用复制构造函数而不是使用右值初始值设定项的移动构造函数? - Why copy constructor is called instead of move constructor with an rvalue initializer? 初始化程序列表向量构造函数 - initializer list vector constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM