为什么必须复制 std::initializer_list 的元素?
Why elements of std::initializer_list have to be copied?
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;
}
我的编译器省略了副本。但是这些副本是否保证被省略?
"Copy initialization" 在 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++ 的初始化规则要求目标被直接初始化 ,没有创建中间对象。即使上下文被称为 "copy initialization",也没有多余的对象。
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;
}
我的编译器省略了副本。但是这些副本是否保证被省略?
"Copy initialization" 在 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++ 的初始化规则要求目标被直接初始化 ,没有创建中间对象。即使上下文被称为 "copy initialization",也没有多余的对象。