Зачем использовать std:: initializer_list по ссылке rvalue или по значению?
Большая часть кода С++ 11, который принимает std::initializer_list
, я видел, берет его по значению, но иногда он берется ссылкой rvalue. Есть ли веские основания для этого?
Например, почти каждый пример, который я встретил, делает следующее:
class A {
public:
A(std::initializer_list<int>);
};
Но я все время вижу, как это происходит:
class B {
public:
B(std::initializer_list<int> &&);
};
Я понимаю использование и назначение ссылок rvalue в целом, но почему один из них предпочтительнее другого в случае std::initializer_list
? Единственное, о чем я мог думать, это то, что class A
позволяет создавать список инициализаторов отдельно, а class B
предотвращает это.
std::initializer_list<int> values {1,2,3,4};
A a(values); // valid
B b(values); // error
Но я не могу думать о хорошей причине, почему предотвращение этого было бы желательным достижением.
Итак, зачем брать std::initializer_list
по ссылке rvalue вместо значения?
Ответы
Ответ 1
Я не уверен, что у меня есть веская причина, но я предполагаю, что автор кода мог подумать, что передача списка инициализатора по значению сделает ненужные копии элементов в списке. Это, конечно, неверно - копирование списка инициализаторов не копирует базовые значения.
Ответ 2
std::initializer_list
воплощает ссылочную семантику даже при передаче по значению, поэтому передача по ссылке в лучшем случае вводит в заблуждение. (Он содержит только указатели, не связанные с владельцем.)
Существуют универсальные ссылки, которые привязаны ко всему, но они не могут быть инициализированы синтаксисом braced-init-list (т.е. { x, y }
), поэтому получение ссылки initializer_list
таким образом приведет к сочетанию обстоятельств.