В чем преимущество использования универсальных ссылок в циклах для диапазонов?

const auto& будет достаточно, если я хочу выполнять операции только для чтения. Тем не менее, я столкнулся с

for (auto&& e : v)  // v is non-const

пару раз недавно. Это заставляет меня задуматься:

Возможно ли, что в некоторых неясных угловых случаях есть некоторое преимущество в производительности при использовании универсальных ссылок по сравнению с auto& или const auto&

(shared_ptr подозревается в неясных угловых случаях)


Обновление Два примера, которые я нашел в моем избранном:

Есть ли какой-либо недостаток использования константной ссылки при переборе основных типов?
Можно ли легко перебирать значения карты, используя цикл for на основе диапазона?

Сосредоточьтесь на вопросе: зачем мне использовать auto & & на основе диапазона для циклов?

91 голос | спросил Ali 30 +04002012-10-30T02:40:42+04:00312012bEurope/MoscowTue, 30 Oct 2012 02:40:42 +0400 2012, 02:40:42

3 ответа


0

Единственное преимущество, которое я вижу, это когда итератор последовательности возвращает ссылку на прокси, и вам нужно работать с этой ссылкой неконстантным способом. Например, рассмотрим:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto& e : v)
        e = true;
}

Это не компилируется, потому что rvalue vector<bool>::reference возвращено из iterator не будет привязываться к неконстантной ссылке на lvalue. Но это будет работать:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto&& e : v)
        e = true;
}

Несмотря на это, я бы не стал так кодировать, если бы вы не знали, что нужно удовлетворить такой вариант использования. То есть Я бы не сделал это безвозмездно, потому что это делает , заставляет людей задуматься о том, что вы делаете. И если бы я это сделал, было бы неплохо добавить комментарий о том, почему:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    // using auto&& so that I can handle the rvalue reference
    //   returned for the vector<bool> case
    for (auto&& e : v)
        e = true;
}

Edit

Этот мой последний случай действительно должен иметь смысл. Если вы знаете, что цикл всегда обрабатывает ссылку на прокси, то auto будет работать так же, как и auto&&. Но когда цикл иногда обрабатывает непрокси-ссылки, а иногда и прокси-ссылки, я думаю, что auto&& станет предпочтительным решением.

ответил Howard Hinnant 30 +04002012-10-30T02:50:12+04:00312012bEurope/MoscowTue, 30 Oct 2012 02:50:12 +0400 2012, 02:50:12
0

Использование auto&& или универсальные ссылки с for -loop имеет то преимущество, что вы захватываете то, что получаете. Для большинства типов итераторов вы, вероятно, получите либо T&, либо T const& для некоторого типа T. Интересный случай, когда разыменование итератора приводит к временному: C ++ 2011 получил смягченные требования, и итераторы не обязательно должны давать lvalue. Использование универсальных ссылок соответствует передаче аргумента в std::for_each():

template <typename InIt, typename F>
F std::for_each(InIt it, InIt end, F f) {
    for (; it != end; ++it) {
        f(*it); // <---------------------- here
    }
    return f;
}

Объект функции f может обрабатывать T&, T const& и T по-разному , Почему тело for -loop на основе диапазона должно быть другим? Конечно, чтобы на самом деле воспользоваться выводом типа с использованием универсальных ссылок, вам необходимо передать их соответствующим образом:

for (auto&& x: range) {
    f(std::forward<decltype(x)>(x));
}

Конечно, использование std::forward() означает, что вы принимаете любые возвращаемые значения для перемещения. Имеет ли смысл подобные объекты в не шаблонном коде, я не знаю (пока?). Я могу себе представить, что использование универсальных ссылок может предложить компилятору больше информации для правильного выполнения. В шаблонном коде он не принимает никакого решения о том, что должно происходить с объектами.

ответил Dietmar Kühl 30 +04002012-10-30T23:35:53+04:00312012bEurope/MoscowTue, 30 Oct 2012 23:35:53 +0400 2012, 23:35:53
0

Я практически всегда использую auto&&. Зачем укусить крайний случай, когда вам не нужно? Его тоже короче набирать, и я просто нахожу его более ... прозрачным. Когда вы используете auto&& x, вы знаете, что x в точности *it, каждый раз.

ответил Puppy 30 +04002012-10-30T23:40:39+04:00312012bEurope/MoscowTue, 30 Oct 2012 23:40:39 +0400 2012, 23:40:39

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132