从初始值设定项列表初始化向量时,为什么不使用移动构造(通过隐式构造函数) [英] Why isn't move construction used when initiating a vector from initializer list (via implicit constructor)

查看:108
本文介绍了从初始值设定项列表初始化向量时,为什么不使用移动构造(通过隐式构造函数)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了演示移动语义,我编写了以下示例代码,其中包含来自int的隐式构造函数.

struct C {
  int i_=0;
  C() {}
  C(int i) : i_( i ) {}
  C( const C& other) :i_(other.i_) {
    std::cout << "A copy construction was made." << i_<<std::endl;
  }
  C& operator=( const C& other) {
    i_= other.i_ ;
    std::cout << "A copy assign was made."<< i_<<std::endl;
    return *this;
  }
  C( C&& other ) noexcept :i_( std::move(other.i_)) {
    std::cout << "A move construction was made." << i_ << std::endl;
  }
  C& operator=( C&& other ) noexcept {
    i_ = std::move(other.i_);
    std::cout << "A move assign was made." << i_ << std::endl;
    return *this;
  }
};

还有

auto vec2 = std::vector<C>{1,2,3,4,5};
cout << "reversing\n";
std::reverse(vec2.begin(),vec2.end());

有输出

A copy construction was made.1
A copy construction was made.2
A copy construction was made.3
A copy construction was made.4
A copy construction was made.5
reversing
A move construction was made.1
A move assign was made.5
A move assign was made.1
A move construction was made.2
A move assign was made.4
A move assign was made.2

现在,反向显示了两个两个交换(每个交换使用一个移动分配和两个移动结构),但是为什么不能从初始化列表中创建临时C对象呢?我以为我有一个整数的初始化列表,但是我现在想知道我之间是否有Cs的初始化列表,而 不能从中移出(作为其const).这是正确的解释吗? -这是怎么回事?

在线演示

解决方案

我以为我有一个整数的初始化列表,但是我现在想知道我之间是否有C的初始化列表,而C不能从中移出(作为其const).这是正确的解释吗?

这是正确的.对于某些模板参数Tvector<C>没有initializer_list<int>构造函数,甚至没有initializer_list<T>构造函数.它的确是一个initializer_list<C>构造函数-它是由您传入的所有int组成的.由于initializer_list的支持是一个const数组,因此您可以获得一堆副本而不是一堆动作.

To demo move semantics, I wrote the following example code, with an implicit constructor from int.

struct C {
  int i_=0;
  C() {}
  C(int i) : i_( i ) {}
  C( const C& other) :i_(other.i_) {
    std::cout << "A copy construction was made." << i_<<std::endl;
  }
  C& operator=( const C& other) {
    i_= other.i_ ;
    std::cout << "A copy assign was made."<< i_<<std::endl;
    return *this;
  }
  C( C&& other ) noexcept :i_( std::move(other.i_)) {
    std::cout << "A move construction was made." << i_ << std::endl;
  }
  C& operator=( C&& other ) noexcept {
    i_ = std::move(other.i_);
    std::cout << "A move assign was made." << i_ << std::endl;
    return *this;
  }
};

And

auto vec2 = std::vector<C>{1,2,3,4,5};
cout << "reversing\n";
std::reverse(vec2.begin(),vec2.end());

With output

A copy construction was made.1
A copy construction was made.2
A copy construction was made.3
A copy construction was made.4
A copy construction was made.5
reversing
A move construction was made.1
A move assign was made.5
A move assign was made.1
A move construction was made.2
A move assign was made.4
A move assign was made.2

Now, the reverse shows the 2 two swaps (each using one move assign and two move constructs), but why are the temporary C objects created from the initializer list not possible to move from? I thought I had an initializer list of integers, but I'm now wondering if what I have in between is an initializer list of Cs, which can't be moved from (as its const). Is this a correct interpretation? - What's going on?

Live demo

解决方案

I thought I had an initializer list of integers, but I'm now wondering if what I have in between is an initializer list of Cs, which can't be moved from (as its const). Is this a correct interpretation?

This is correct. vector<C> does not have an initializer_list<int> constructor or even an initializer_list<T> constructor for some template parameter T. What it does have is an initializer_list<C> constructor - which is built up from all the ints you pass in. Since the backing of initializer_list is a const array, you get a bunch of copies instead of a bunch of moves.

这篇关于从初始值设定项列表初始化向量时,为什么不使用移动构造(通过隐式构造函数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆