首页 > 解决方案 > 为什么 C++ 将 std::initializer_list 的元素类型设为 const?

问题描述

std::initializer_list<std::string>例如,我通常使用{"foo"s, "bar"s}来填充容器。

显然,std::initializer_list<std::string>包含临时字符串,我可以将它们移动到容器中:

#include <string>
#include <list>

using namespace std::literals;    

void f(std::initializer_list<std::string> il)
{
    std::list<std::string> coll;
    for (auto&& tmp_str : il)
    {
        coll.emplace_back(std::move(tmp_str)); // Why ok here?
    }
}

int main()
{
    f({"foo"s, "bar"s});
}

但是,根据cppref

std::initializer_list 类型的对象是一个轻量级代理对象,它提供对 const T 类型的对象数组的访问。

为什么 C++ 将 std::initializer_list 的元素类型设为 const?

标签: c++c++14standardsrvalue-reference

解决方案


显然,std::initializer_list<std::string>包含临时字符串

是吗?允许将其实现为瘦代理。在这种情况下,它将引用原始实例"foo"s, "bar"s

...我可以将它们移动到容器中

我不信。std::move()一个const左值引用产生...一个const右值引用。这与作为可行候选人的移动构造函数不太匹配。

#include <iostream>

struct A {
    A() { std::cout << "A()\n"; }
    A(A&&) { std::cout << "A(&&)\n"; }
    A(A const&) { std::cout << "A(const&)\n"; }
};

int main() {
    const A a;
    A b(std::move(a));
}

印刷

A()
A(const&)

MSVC 2019 甚至警告:

Warning C26478  Don't use std::move on constant variables. (es.56).

另请参阅为什么我们可以std::moveconst对象上使用?


推荐阅读