如何移动initializer_list的元素?

Dan*_*rey 13 c++ initializer-list move-semantics c++11

假设您有一个类型变量,std::vector<std::string>并使用初始化列表初始化它:

using V = std::vector<std::string>;
V v = { "Hello", "little", "world", "of", "move", "semantics" };
Run Code Online (Sandbox Code Playgroud)

编译器将为std::string每个字符串文字创建一个临时文件,在这些文件上创建一个初始化列表,然后调用ctor V并创建向量.ctor不知道所有这些字符串都是临时字符串,所以它正在复制每个字符串.

我没有在标准中找到任何允许矢量ctor在临时时移动元素的东西.

我错过了什么或使用初始化程序列表导致不必要的副本?我正在编写类,这个问题可能会导致代码效率低下.任何避免不必要的副本的技术将不胜感激.

Che*_*Alf 5

没有办法避免从a复制initializer_list<string>,因为标准定义了一个构造函数的调用,它采用初始化列表参数,从花括号初始化器作为实际参数,如下所示(强调添加):

C++14§8.5.4/ 5

"类型的对象std::initializer_list<E>是从初始化列表构造的,就好像实现分配了一个临时N的类型元素数组const E,其中N是初始化列表中元素的数量

恕我直言,这真的很不幸.

解决方法(对于您自己的类)是接受的initializer_list<char const*>.


以下是适用于此的变通方法的示例std::vector<string>.为此,在不控制类的代码的情况下,它涉及initializer_list明确声明数据数组(实际上是).这与初始化程序列表机制旨在避免的C++ 03一样:

#include <vector>
#include <initializer_list>
#include <iostream>
#include <iterator>              // std::begin, std::end
using namespace std;

struct My_string
{
    char const* const ps;

    My_string( char const* const s )
        : ps( s )
    {
        cout << "  My_string(*) <- '" << s << "'" << endl;
    }

    My_string( My_string const& other )
        : ps( other.ps )
    {
        cout << "  My_string(const&) <- '" << other.ps << "'" << endl;
    };

    My_string( My_string&& other )
        : ps( other.ps )
    {
        cout << "  My_string(&&) <- '" << other.ps << "'" << endl;
    };
};

auto main() -> int
{
    cout << "Making vector a." << endl;
    vector<My_string> const a   = {"a1", "a2", "a3"};
    cout << "Making data for vector b." << endl;
    auto const b_data           = { "b1", "b2", "b3" };
    cout << "Making vector b." << endl;
    vector<My_string> const b( begin( b_data ), end( b_data ) );
}
Run Code Online (Sandbox Code Playgroud)

输出:

Making vector a.
  My_string(*) <- 'a1'
  My_string(*) <- 'a2'
  My_string(*) <- 'a3'
  My_string(const&) <- 'a1'
  My_string(const&) <- 'a2'
  My_string(const&) <- 'a3'
Making data for vector b.
Making vector b.
  My_string(*) <- 'b1'
  My_string(*) <- 'b2'
  My_string(*) <- 'b3'