【问题标题】:std::initializer_list and reference typesstd::initializer_list 和引用类型
【发布时间】:2014-06-08 18:28:53
【问题描述】:

std::initializer_list 可以包含引用类型(右值和左值)吗?还是必须使用指针或引用包装器(例如std::ref)?

编辑:

也许需要进一步澄清:

我有一个成员变量::std::vector<std::function<void()> >,我想将一个 lambda 对象转发到其中。这通常可以使用emplace_back 来完成,但我想在构造函数的初始化列表中进行。唉,正如我所读到的,这将使转发变得不可能。

【问题讨论】:

  • 你的意思是std::initializer_list<int&> a = {...};
  • @RSahu 是的,或者 &&,但我主要考虑了类引用类型。

标签: c++ c++11 initializer-list


【解决方案1】:

std::initializer_list 可以包含引用类型(右值和左值)吗?

std::initializer_list<T> 不包含对其元素的引用。它通过将其值保存为const 对象来使用复制语义

18.9 初始化列表 [support.initlist]

initializer_list<E> 类型的对象提供对const E 类型对象数组的访问。

initializer_list 的引用将导致编译错误,因为迭代器使用的是迭代指针:

#include <initializer_list>
int main()
{
    int x;
    std::initializer_list<int&> l = {x};

    // In instantiation of 'class std::initializer_list<int&>':
    // error: forming pointer to reference type 'int&'

    // typedef const _E*  iterator;
}

initializer_list 也不支持移动语义,因为无法移动 const 对象。如果您希望维护引用语义,将对象保存在 std::reference_wrapper&lt;T&gt; 中是最可行的解决方案。

【讨论】:

  • 我相信它们确实支持一种移动语义,因为您在技术上可以“移动”const &amp;&amp;
  • @user1095108 不,他们没有。移动不会仅仅通过调用std::move() 而发生,它只是对右值的强制转换。采用非 const 右值引用 (X&amp;&amp;) 的构造函数是实际发生移动的地方,在某些情况下“移动”const 对象实际上会创建一个副本,而在其他情况下会出现编译错误。
  • 我知道,但没有什么能阻止移动构造函数复制而不是移动。我只是在吹毛求疵。
【解决方案2】:

来自http://www.cplusplus.com/reference/initializer_list/initializer_list/

initializer_list 对象像数组一样自动构造 类型 T 的元素已分配

因此它们不能与std::initializer_list&lt;int&amp;&gt; 之类的东西一起使用。原因与以下给出编译器错误的原因相同

int& arr[20];

错误:将“arr”声明为引用数组

这是由 C++ 标准规定的:https://stackoverflow.com/a/1164306/1938163

【讨论】:

  • 我会说是的,你可以分配一个数组。
猜你喜欢
  • 1970-01-01
  • 2015-08-02
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
相关资源
最近更新 更多