c++ - 为什么必须复制 std::initializer_list 的元素?

标签 c++ move-semantics initializer-list

cppreference 说:

The underlying array is a temporary array of type const T[N], in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). The underlying array may be allocated in read-only memory.

这个决定背后的理由是什么?为什么搬家不好?

复制省略怎么样?

struct A { A(const A&){ std::cout << "Oh no, a copy!\n"; } };
struct B { B(std::initializer_list<A> il); };

int main()
{
    B b{ A{} };
    return 0;
}

我的编译器省略了拷贝。但这些拷贝一定会被省略吗?

最佳答案

C++ 中的“复制初始化”并不意味着一定会复制内容。它只是发生初始化的约束的正式名称。例如,当拷贝初始化时,显式 c'tors 不是候选者。所以下面的代码will be ill-formed

#include <iostream>
#include <initializer_list>

struct A {
    explicit A() = default;
    A(const A&){ std::cout << "Oh no, a copy!\n"; } 
};
struct B { B(std::initializer_list<A> il); };

int main()
{
    B b{ {} };
    return 0;
}

列表中的单个成员需要从 {} 进行复制初始化,这需要调用默认的 c'tor。但是,由于 c'tor 被标记为显式,因此无法进行此初始化。

复制省略在 C++17 之前当然是可能的,并且在某些上下文中的 C++17 中是强制的。在您的示例中,在 C++17 编译器下,由于您提供的初始化程序是纯右值(纯右值,而不是对象),因此 C++ 的初始化规则要求直接初始化目标 ,没有创建中间对象。尽管上下文被称为“复制初始化”,但没有多余的对象。

关于c++ - 为什么必须复制 std::initializer_list 的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60862812/

相关文章:

c++ - 是否建议指定例如vector<t> 在我的公共(public)界面?

c++ - 是否有一个不会被省略的 move 构造的简单示例?

reference - 将两个对象(其中一个对象持有对另一个对象的引用)传递到线程中

c++ - 在 lambda 中复制 initializer_list 是否合法?

c++ - 如何格式化 thrust::copy(ostream_iterator)

python - 为 python 包装 c++ 类(使用 opencv),给出 "undefined symbol"

c++ - C++11 初始化列表可以与动态数组一起使用吗?

c++ - 在 Lambda 捕获中构建 intializer_list<string>

c++ - 将 4 字节十六进制字符串转换为整数