LINUX.ORG.RU

Карта указателей, ссылок и for по диапазону

 , ,


0

3

Привет, ЛОР.

Тут такая задачка возникла. Поступает на вход массив неких структур, которые в чём-то схожи, а в чём-то различны и обрабатывать их надо и как единое целое, и по типам (записи разных типов перемешаны). Чтобы не копировать данные туда-сюда и вообще не нарушать целостность, я подумал «а давай-ка сделаю три контейнера ссылок и пусть они ссылаются на оригинальные структуры». Важно: структуры в процессе обработки меняются, т.е. константными я их делать не могу.

Попробовал примерно так:

struct AnyS {
    int a, b, c;
};

std::list<AnyS> anyList;
std::map<int, AnyS&> refs0, refs1;

    AnyS any;
    any.a = 0;
    anyList.push_back(any);

    int i=0;
    for (AnyS& yaAny: anyList) {
        if (yaAny.a==0)
            refs0[i] = yaAny;
        // Тут м.б. рациональнее было бы сделать switch, но не суть, это демо
        i++;
    }

На строке с присвоением получаю ошибку

/usr/include/c++/11/tuple:1824: ошибка: value-initialization of reference type ‘AnyS&’

Т.е. оно пытается присваивать по значению, хотя я хотел явно противоположного, и у него это не получается.

А что самое смешное? А то, что если я отказываюсь от ссылок и работаю по старинке с указателями, то всё прекрасно работает! Примерно так:

// ...
std::map<int, AnyS*> refs0, refs1;
//...
    for (AnyS& yaAny: anyList) {
        if (yaAny.a==0)
            refs0[i] = &yaAny;
        i++;
    }

Но нельзя ли всё-таки как-то заставить работать вариант со ссылками? Они, типа, безопаснее, и красивее и вообще сейчас считается, что работа с указателями это фи.

Я, конечно, догадываюсь, что я как-то неправильно использую range-based for… но вот как правильно…

P.S. GCC 11.3.1, если это важно.

★★★★★

Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от kvpfs_2

само отвалится в нужных местах

Почему оно отваливается там? Может такая необходимость возникнуть в пользовательском классе? А применение ссылки лишь инструмент, ровно как и явное удаление методов.

куча говна

«слова не мальчика, но мужа!»

«Note that using a reference member is almost always wrong»

«almost always wrong»

core guidelines

к ним приложили руки пусть и грамотные люди, но в большей части те же, кто пилил gsl, тот же Саттер (раньше как раз в MS работал). Так что догматично я их тоже не воспринимаю. Как хорошие рекомендации в общем, особенно, если нет понимания механизмов - очень даже. Но слепо следовать всегда - простите.

По ссылкам там не дано разъяснения и раньше в этой фразе фигурировала ещё и отсылка к auto_ptr. Если проблемы последнего обсосали везде, где только можно и ровно по той же причине задепрекйтили, то по ссылке - туман. Я вижу ровно две причины, по которой имеет смысл отказываться:

  • Класс не владеет ресурсом - опасность висячей ссылки. Невладеющий указатель тут не спасёт. И ссылка здесь воспринимается как конракт на уровне языка дающий гарантии пользователю: объект живёт, пока твой класс живёт, он точно не nullptr и без дополнительный аннотаций, типа not_null.
  • Отваливается копирование и конструктор по умолчанию. Но это далеко не всегда проблема. И иногда и желаемое поведение.

Ну и от foo& _member в плане исчезновения operator= проблема ровно такая же, как от const foo _member. И развивая твою отсылку на Note, есть более детальное правило:

Но тут уже более конкретно: «in a copyable or movable type». Ну а если им нет необходимости такими быть?

Да, Страуструп предложил развернуть этот нотайс до правила, на что Саттер предложил уточнить вышеупомянутый C.12, но за 4 года так и не сподобились: видать очень нужно и проблема очень острая.

Ещё есть и такая дискуссия конкретно по этому нотайсу и вот эта позиция точно ложится на мои высказывания выше. Вообще, там есть и про std::reference_wrapper и чисто косметические неудобства типа вызова .get() на нём, но всё сводится к акценту на almost и пожелания конкретики. А общая канва: под задачу инструмент. Дискуссии 5 лет как, а метры не удосужились конкретики привести.

@hobbit, прости, что засираем тему :))))

hatred ★★★
()
Последнее исправление: hatred (всего исправлений: 1)
Ответ на: комментарий от hatred

прости, что засираем тему

Да не, я как раз доволен, что такое познавательное обсуждение получилось.

Сам я, как уже написал выше, остался на варианте с указателями: дёшево и сердито. Разумеется, всё, что должно быть проверено на ноль и на время жизни (порядок удаления) – проверяется.

hobbit ★★★★★
() автор топика
Последнее исправление: hobbit (всего исправлений: 1)