Most of the C++11 code that takes std::initializer_list
I've seen takes it by value, but sometimes it is taken by rvalue reference. Is there any good reason to do this?
For example, almost every example I've come across does this:
class A {
public:
A(std::initializer_list<int>);
};
But I keep seeing this done occasionally:
class B {
public:
B(std::initializer_list<int> &&);
};
I understand the use and purpose of rvalue references in general, but why would one of these be preferred over the other in the case of a std::initializer_list
? The only thing I could think of is that class A
allows the initializer list to be constructed separately, and class B
prevents this.
std::initializer_list<int> values {1,2,3,4};
A a(values); // valid
B b(values); // error
But I can't think of a good reason why preventing that would be a desirable thing to accomplish.
So, why would one take a std::initializer_list
by rvalue reference instead of by value?
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
std::initializer_list This type is used to access the values in a C++ initialization list, which is a list of elements of type const T .
An lvalue const reference can bind to an lvalue or to an rvalue. The syntax for a reference to an rvalue of type T is written as T&& . An rvalue reference refers to a movable value—a value whose contents we don't need to preserve after we've used it (for example, a temporary).
I'm not sure I have a good reason, but my guess would be that the author of the code may have thought that passing an initializer list by value would make unnecessary copies of the elements in the list. This is, of course, not true - copying an initializer list does not copy the underlying values.
std::initializer_list
embodies reference semantics even when passed by value, so passing by reference is at best misleading. (It only contains non-owning pointers.)
There are universal references which bind to anything, but they cannot be initialized by the braced-init-list syntax (i.e. { x, y }
), so getting an initializer_list
reference that way would take a combination of circumstances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With