41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
||||||
1 | ||||||
Возможна ли инициализация в инициализации?23.08.2016, 12:38. Показов 1603. Ответов 24
Метки нет (Все метки)
Изучая новый стандарт, заинтересовался: а можно ли как-то сделать массив указателей, например, на тип int, инициализируя ссылочные переменные, на которые указывали бы указатели, в одном выражении? Как-то так:
0
|
23.08.2016, 12:38 | |
Ответы с готовыми решениями:
24
Инициализация (ООП, списки инициализации) Инициализация в теле конструктора или в списке инициализации. Инициализация не агрегированных данных списка инициализации не допускается Инициализация в теле конструктора или в списке инициализации, есть ли разница в сгенерированном коде? |
23.08.2016, 12:48 | 2 | |||||
Lyosha12, даже если бы у Вас получилось, это были бы указатели на временные объекты, которые удалились бы следом и указатели в Вашем массиве бы протухли
Добавлено через 3 минуты Но реализовать это всё можно, например, так:
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 13:12 [ТС] | 3 |
С временными объектами ещё не знакомился, но полагаю, что, если они не закреплены за какой-то ссылкой, то они удаляются, как только ссылка выходит из области видимости.
В приведенном примере Вы дали жизнь временному объекту, инициализировав ссылку адресом rvalue. Верно? И с объектом ничего не случится, пока не будет уничтожена эта ссылка? Или в этом и отличие: rvalue-ссылки именно временные объекты и ссылки на них могут устареть, а обычная инициализация переменной как-то бронирует адрес временного объекта, созданного через int()? (Вопрос: как? ) Но тема о другом. Я не хотел иметь дело с временными объектами. В списке инициализации инициализировались бы переменные типа int, а уже на них ссылались бы указатели в массиве.
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
||||||
23.08.2016, 13:14 | 4 | |||||
Сообщение было отмечено Lyosha12 как решение
Решение
Внимание, смертельный номер (дома не повторять):
PS. Естественно все вышеописанное - шутка, не надо такое писать.
3
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 13:51 [ТС] | 5 |
malloc выделяет место в куче, а alloca - в стеке. Но как можно (и зачем) выделять место в стеке? На лекциях нам говорили, что массив, размещённый на стеке, должен иметь строго определённый размер, так как память выделяется при компиляции и после неё мы над памятью в стеке не властны.
И почему Вы не рекомендуете заниматься размещением-инициализацией памяти, если в вики прямо говорится об практическом использовании? Получается, что для временных объектов память отводится строго для нужд использования их в операциях, конкретно, в регистрах процессора? Потому-то они и временные? А зарезервировав память, которую отдаст ОС из RAM, мы получим уже долгоживущий объект. Верно?
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
||||||
23.08.2016, 14:00 | 6 | |||||
Так заведено, что объекты автоматических переменных размещаются в стеке.
Причем здесь массив? Массив тут один, и он был и в изначальном посте. Он также размещен в стеке. И да, он имеет строго определенный размер, заданный на этапе компиляции - 2. Никаких разночтений с лекцией пока что Что касается alloca, то она тоже выделяет память в стеке, подобно тому, как поступает компилятор. Более того, по ссылке выше написано, что в GNU реализации - это не функция, а специальная инструкция компилятора, которая резервирует место в стеке. "Резервирование", обычно заключается в смещении специального регистра - указателя стека - на заданную величину. Я говорил не про размещающий new как таковой. А про комбинацию alloca + placement new, и, в частности, идею твоего стартового поста. Не нужно экономить на строчках. Тем не менее, мой пример на данный момент является наиболее близким решением поставленной тобой задачи (за исключением синтаксиса). Т.е. пример выше - это почти полный эквивалент вот такого кода:
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
||||||
23.08.2016, 14:25 [ТС] | 7 | |||||
То есть, память всё-таки выделяется при компиляции... И такую функцию, наверно, создавали для типов, размер которых отличен от стандартных (верно?).
Но ведь то же самое, на мой взгляд, делает и это:
Да, я знаю, что экономить на строках и читаемости - плохо. Но это оправдывает себя, когда преподаватели старой закалки требуют печатать все программы. Вот прям исходники. Да и не знать особенностей синтаксиса - тоже как-то не хорошо. Добавлено через 3 минуты В принципе, инициализация в инициализации, как Вы показали, возможна, ведь для инициализации массива указателей требуются адреса, которые возвращает оператор new. И, как я вижу из примеров, объявить и ссылку на объект, и взять её адрес, и присвоить значению указателя, используя всего одно выражение, нельзя. (Не учитывая извращения с макросами) Добавлено через 6 минут Перегнул палку намёков. Имел ввиду, что Вы выделяете так память в стеке уже во время выполнения.
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
23.08.2016, 14:33 | 8 |
Не совсем. Функцию создавали, чтобы иметь возможность запрашивать со стека произвольный (в границах стека, конечно) кусок памяти.
Указатель стека мы и на этапе исполнения можем изменить, например ассемблерной вставкой. Просто эта функция делает это заведомо правильно. Нет. Здесь объекты размещаются в куче, следовательно за временем жизни переменных следить должен программист. Этот пример не аналогичен твоему псевдокоду. У тебя проблемы в понимании работы памяти. Лучше начать с этого - синтаксис, особенно такой редкоиспользуемый, подождет. Это уже вопрос экономии бумаги. Добавлено через 4 минуты Начать с того, что ты сильно путаешься в терминах. Что есть ссылка в твоем понимании здесь? В данном коде на этапе компиляции. Т.к. используется константа времени компиляции, которую дает sizeof. Но в целом да, параметром allocа может быть и вычесленное на этапе исполнения число.
1
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
||||||
23.08.2016, 14:39 [ТС] | 9 | |||||
Спорить не буду. Читаю материалы по этой теме уже вторую неделю, но всё как-то абстрактно и нет "физики". Узнав про виртуальную память, которую выделяет система особняком от физической, ситуация немного прояснилась. Но вопросы про выход за границы массива и ошибки сегментации остались. "Но это уже совсем другая история".
Да, я понял. Вы делаете имитацию стековой переменной, только отрываете от неё имя. Действительно варварство А вот про такую особенность мне не говорили... Ну, опять же, из лекции: "Выделять место на стеке во время выполнения нельзя". Под указателем стека Вы понимаете размер памяти, отведённой ОС процессу? Добавлено через 2 минуты Ссылка, как мне объясняли, лишь имя объекта:
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
23.08.2016, 14:51 | 10 |
Средствами языка С++, да невозможно. В С, начиная со стандарат 99 года - возможно (см. VLA).
Впрочем, зависит как на это смотреть: компилятор только кодирует в двоичный код операции смещения регистра ESP. На этапе исполнения эти операции выполняются процессором и значение регистра меняется. Конкретное значение всегда меняется на этапе исполнения Поэтому и код с alloca не сильно отличается от того, что происходит по умолчанию. Просто значение для смещения мы подставляем сами. Под указателем стека в данном случае я понимаю реализацию аппаратного стека в x86-совместимых процессорах, т.е. регистр ESP. Ссылка имя объекта - да. Но не всякое имя объекта - ссылка. Добавлено через 1 минуту Тебе бы ассемблер поизучать.
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 14:55 [ТС] | 11 |
Да. Я имел ввиду, что, инициализируя массив указателей, мы не сможем одновременно и создавать ссылки на объекты, к которым должны привязываться и указатели.
Добавлено через 18 секунд Давно горю желанием.
0
|
2337 / 1825 / 753
Регистрация: 27.07.2012
Сообщений: 5,400
|
||||||
23.08.2016, 15:02 | 12 | |||||
Неверное впечатление. Ссылка может быть на любой объект. Иногда ссылка - способ дать имя безымянному объекту:
1
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
23.08.2016, 15:03 | 13 |
Ты ушел в частности. Все же проще гораздо:
Объявлять переменные (в том числе ссылки) в принципе нельзя в списке иницилизации. Этого нам синтаксис не позволит. Мы можем попытаться создать объект (как во втором посте), но он будет жить до конца выражения, а потом помрет, оставив висячий указатель. Или можем попытаться зарезервировать память внешним инструментом, чтобы проинициализировать в ней нужный нам объект. В итоге во всей этой цепочке термин "ссылка" вообще лишний. Ты, употребляя его, только запутываешь себя.
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 15:16 [ТС] | 14 |
Я употребил термин "ссылка", так как изначально хотел работать с объектами, адреса которых были бы неотделимы от имении, за которым они закреплены (ссылкой), а так же массивом указателей на такие именованные адреса, который я бы удобно передал в функцию.
Если Вы имеете в виду, что ссылка и адрес - это синонимы, то да, я, наверно, употребил термин некорректно, так как изначально представлял её себе "переменной типа указатель, при обращении к которой не нужно разыменовывать её, дабы получить содержимое по адресу в ней (или её адресу)".
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|||||||||||
23.08.2016, 15:21 | 15 | ||||||||||
Да нет в этом примере ссылок.
Вообще нет. Если ты хотел, чтобы и имена объявленных переменных также были доступны ниже по коду, то см. еще раз пост 13. Запись
Ссылка в С++ - это вот:
И это не синонимы
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 15:29 [ТС] | 16 |
Так, теперь я уже точно запутался. Если объявленная переменная - не ссылка, тогда что же это, если мы получаем значение этой переменной точно так же, как получаем значение по ссылке на эту переменную?
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
23.08.2016, 15:36 | 17 |
Ссылка - это псевдоним переменной (в высокоуровневом смысле).
Вот есть ты, а есть твой псевдоним на форуме. Скажи мне, ты ссылка? Я так не думаю. А вот твой псевдоним - да. Он - ссылка, на тебя. Определение переменной создает объект этой переменной. Он первичен, ссылка - вторична. PS. Объявление навроде int a = 5; также является и определением. Но это уже то, о чем лучше позже. А то ты точно меня не отпустишь уже
1
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 15:40 [ТС] | 18 |
Разница лишь в абстракции? Работаем-то с адресами в любом случае? И что ссылка, что "объект переменной" будут указывать на один и тот же адрес, будут совершать одни и те же допустимые операции. Ведь, используя переменные вне контекста их объявлений, мы даже не задумываемся где оригинальная ссылка. Работаем же с адресами-ссылками. В чём я ошибаюсь? Как мне тогда называть "ссылку, инициализированную объектом"? Ну, ладно, переменная. Но это общее же понятие...
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
23.08.2016, 15:44 | 19 |
Да, если отойти от абстракций и несколько все упростить (забыть про оптимизации компилятора, про переменные в регистрах, про вычисление на этапе компиляции), то да. Работаем с адресами.
0
|
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
|
|
23.08.2016, 15:46 [ТС] | 20 |
Не по теме: Форумы за тем и нужны, что можно не отвечать сразу :D Добавлено через 58 секунд В любом случае, спасибо, что указали на пробелы
0
|
23.08.2016, 15:46 | |
23.08.2016, 15:46 | |
Помогаю со студенческими работами здесь
20
Инициализация полей объекта в заголовочном файле против списка инициализации Warning C4244: инициализация: преобразование "__int64" в "int", возможна потеря данных Возможна ли инициализация объекта класса в момент передачи параметра в Возможна ли инициализация связного списка в функции void (void)? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |