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)
12 сентября 2025 г.
Ответ на: комментарий от PRN

Я сейчас тебя шокирую))) Ссылки - это синтаксический сахар в плюсах над указателями, которые необходимо проиницилизировать и нельзя переприсвоить, есть еще тонкости с константным рефенсом

а я сейчас тебя шокирую — нет — это не сахар над указателями — это типичный «хинт» для компилятора — в отличии от указателей они не являются объектами, и не описывается когда и будет ли вообще под них выделяться память (материализация).
https://eel.is/c draft/dcl.ref#4

safocl ★★
()

мне кажется, ты пытаешься переизобрести boost::intrusive. я даже проверила, не втащили ли их ещё в стандарт. вроде пока нет. но библиотека древняя и она header-only.

и буст ещё запилил некий pointer_container, но тут я хз, я это не тыкала палочкой.

Iron_Bug ★★★★★
()
Ответ на: комментарий от AntonI

Это как О_О? Ссылка (в плюсовых терминах) это указатель покрытый приторной синтаксической глазурью.

двойка.

safocl ★★
()
Ответ на: комментарий от safocl

Ваша любовь ко всему самому «модному / молодёжному» широко известна. Но пишу я не из-за этого (и не для вас, собственно): наврал я - «flat» containers добавили в буст слегка позже, в 1.48 (2011 год).

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

ну вот видишь, ты уже явно привязался к моим замечаниям, — надеюсь будешь исправлять своё мышление в более актуальную сторону.

safocl ★★
()
Ответ на: комментарий от safocl

https://eel.is/c++draft/dcl.ref#4

Сказал как пёрнул! Это ни разу не противоречит тому что я написал. В плюсах много что оптимизированно.

PS. В следующий раз попробуй промолчать - за умного сойдешь XD

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

Похоже мало того что ты любишь изображать из себя клоуна, так еще и ж0пой читаешь. То что ты кинул, никак не опровергает мной написанное.

PRN
()
Ответ на: комментарий от safocl

facepalm.bmp

Если бы указатель и ссылка были бы идентичны, в указателях не было бы никакого смысла. Логично что они будут в чём-то отличаться. Завязывать с веществами, они тебе на пользу не идут)

PRN
()
Ответ на: комментарий от PRN

Логично что они будут в чём-то отличаться.

но они не в «чём-то» отличаются — а полностью разные сущности языка — ссылки вообще это лишь хинт компилятору, что нужно использовать «вон ту сущность» — указатель же полноценный объект, который компилятор почти никогда не может никак оптимизировать.

safocl ★★
()
Ответ на: комментарий от safocl

полностью разные сущности языка

Да да, и оба предназначены не для того чтобы ссылаться на какой-то объект)) смешнее на лоре за сегодня уже не найти))

PRN
()
Ответ на: комментарий от PRN

указатель не ссылается, а указывает — буквально — говорит, «я храню информацию где искать таргетный объект»

safocl ★★
()
Ответ на: комментарий от PRN

ну и ты тут явно херобору спорол — поскольку предназначение никак не может противоречить различности сущностности. Разные сущности могут так же иметь одно предназначение...
видно что ты даже не можешь сам себе объяснить, для чего тебе вообще отвечать в мой адрес, поскольку сам уже понял что неправ, но признаться публично не можешь

safocl ★★
()
Последнее исправление: safocl (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.