Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
1

Интересная инициализация ссылки

06.07.2013, 22:06. Показов 1700. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток.
Рассмотрим вот такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Base
{
public:
    Base(Base *instance, 
         unsigned int NumElems):
      vec(NumElems),
      vec_ref(instance->vec)
    {}
    std::vector<float> vec;
    std::vector<float>& vec_ref;
};
 
class Der : public Base
{
public:
    Der() : Base(nullptr, 5){}
};
Эта штука вполне удачно компилируется, однако, смущает то, как инициализируется ссылка vec_ref в конструкторе - ссылка ведь не может быть NULL как указатель. Получается, что в конструкторе Base происходит нечто вроде nullptr->vec. Так что же в данном случае представляет собой vec_ref после инициализации и насколько безопасен такой код?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.07.2013, 22:06
Ответы с готовыми решениями:

Инициализация ссылки
Приветствую всех. Есть класс, который обрабатывает объект. Объект передается в класс по ссылке...

Инициализация ссылки в методе
Здравствуйте, уважаемые участники форума, в C можно было передать указатель в параметрах метода и...

Что такое инициализация сегментов или инициализация регистров?
Подскажите, что такое инициализация сегментов или инициализация регистров? Вот строчка программы из...

Как заменить все ссылки на текст кроме ссылки моего сайта?
Всем привет! Есть выражение и есть текст ссылками. Где ссылки заменяю на слова &quot;Ссылки запрещены!&quot;....

19
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:09 2
это код с неопределенным поведением и скорее всего крашем.
синтаксически все верно. но в рантайме начнутся проблемы, т.к. тут попытка обратится к члену какого-то объекта через нулевой указатель.
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:11  [ТС] 3
DU, lда, это я уже проверил - дамп памяти получился. но если не обращаться к этому элементу, то все вроде бы ок. я вот хотел бы уточнить, не чревато ли это утечками какими-нибудь, если код оставить как есть, но не обращаться к элементу vec_ref, инициализированному как показано выше?
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,113
Записей в блоге: 2
06.07.2013, 22:12 4
Цитата Сообщение от Gorillych Посмотреть сообщение
ссылка ведь не может быть NULL как указатель
Нет, так и в коде этого тоже нет.
Цитата Сообщение от Gorillych Посмотреть сообщение
Получается, что в конструкторе Base происходит нечто вроде nullptr->vec.
Ну да, ссылка на вектор инициализируется вектором. Что не так?
Цитата Сообщение от Gorillych Посмотреть сообщение
насколько безопасен такой код?
Не на сколько, он же в рантайме сломается
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:14  [ТС] 5
Цитата Сообщение от Kastaneda Посмотреть сообщение
Не на сколько, он же в рантайме сломается
сломается, только если к этой ссылке обратиться
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,113
Записей в блоге: 2
06.07.2013, 22:17 6
Цитата Сообщение от Gorillych Посмотреть сообщение
сломается, только если к этой ссылке обратиться
а nullptr->vec не смущает?
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
06.07.2013, 22:17 7
Gorillych, Ссылка безопаснее лишь тем, что не может быть не инициализированной, но никто не запрещает инмциализировать ее не верными данными
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:19 8
ну есть негласное правило, когда лучше ссылки использовать, а когда указатели.
если ваш класс может корректно работать в случае, когда ему передадут нулевой указатель (типа специально предусмотрена такая возможность для какого-нибудь там дефолтного поведения) - то передаем в него указатель.
если не может (в вашем случае - не может. т.к. внутренний член инициализируется членом, получаемым от переданного в конструктор объекта), то тут лучше воспользоваться ссылкой, т.к. ссылки вроде как как всегда ссылаются на какой-то объект. "вроде как" - это не всегда так, но в этом случае ответственность на вызывающей стороне. она должна следить, чтобы в конструктор приходила ссылка на существующий объект. т.о., использование ссылки вместо указателя намекает вызывающей стороне что сюда нужно отдавать что-то существующее, иначе сам дурак.
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:34  [ТС] 9
Croessmah, жаль, лучше бы уж компилятор ругался в таких случаях

Добавлено через 11 минут
Цитата Сообщение от Kastaneda Посмотреть сообщение
а nullptr->vec не смущает?
смущает, конечно) поэтому и тему создал

Добавлено через 3 минуты
DU, если vec_ref будет не ссылкой, а указателем, от этого что-то принципиально изменится в рантайме?
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,113
Записей в блоге: 2
06.07.2013, 22:38 10
Цитата Сообщение от Gorillych Посмотреть сообщение
смущает, конечно) поэтому и тему создал
Так оно сломается в момент обращения по nullptr, т.е. еще до инициализации ссылки.

Добавлено через 45 секунд
Цитата Сообщение от Gorillych Посмотреть сообщение
если vec_ref будет не ссылкой, а указателем, от этого что-то принципиально изменится в рантайме?
нет, просто в этом случае оно упадет в момент инициализации указателя, а не в момент инициализации ссылки
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:44 11
нет. не будет. ссылки и указатели транслируются компилятором в один и тот же бинарный код.

на счет сломается - не факт. поскольку Obj* obj = &superOjbPtr->obj - это не изменяющее обращение.
т.к. компилятор знает, смещение в памяти объекта obj относительно объекта superObj и в данном случае мы получаем указатель на obj, то компилятор может просто сгенерировать код obj = superObjPtr + смещение = 0 + смещение. т.е. тут арифметика указателей вполне может оказаться так, что ничего не случится. а вот при попытке изменить obj за счет вызова какого-нибудь метода или просто изменить, если это какой-нибудь инт, вот тут будут проблемы, т.к. obj указывает хз куда.
1
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,113
Записей в блоге: 2
06.07.2013, 22:52 12
Цитата Сообщение от DU Посмотреть сообщение
компилятор может просто сгенерировать код obj = superObjPtr + смещение = 0 + смещение.
Ну да, так оно и будет, только адрес получится очень маленьким (если только смещение не равно паре гигов ), а в современных десктопных ОСях это тоже недопустимо. Может под какое-нибудь специфичное устройство со специфичной ОСью это и будет работать (всмысле не скрэшится), но винда и линукс на х86 выкинут исключение.

P.S. хотя замечание в целом верное, я что-то неподумав написал.
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:55 13
вот тестик в 2012 студии. инициализация через нулевой указатель не крашится. крашится попытка изменения.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
struct Struct
{
  int structMember;
};
 
struct SuperStruct
{
  char offset[8];
  Struct str;
};
 
int main()
{
  SuperStruct* superStruct = nullptr;
  Struct* structPtr = &superStruct->str;
  Struct& structRef = superStruct->str;
  std::cout << "address of struct = 0x" << structPtr << std::endl;
  std::cout << "address of struct = 0x" << &structRef << std::endl;
//  structRef.structMember = 5; // runtime error.
  return 0;
}
output:
address of struct = 0x00000008
address of struct = 0x00000008
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,113
Записей в блоге: 2
06.07.2013, 22:56 14
Цитата Сообщение от DU Посмотреть сообщение
а вот при попытке изменить obj за счет вызова какого-нибудь метода или просто изменить. если это какой-нибудь инт, вот тут будут проблемы, т.к. obj указывает хз куда.
Да, верно. Вот это
Цитата Сообщение от Kastaneda Посмотреть сообщение
но винда и линукс на х86 выкинут исключение.
я писал опять не думая У меня в голове картина по другому выглядела (там почему-то было obj = *(0 + offset))
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.07.2013, 23:00 15
Цитата Сообщение от Gorillych Посмотреть сообщение
ссылка ведь не может быть NULL как указатель.
Может. Но стать NULL она не может, а только быть изначально. И поменяться может только NULL ссылка.
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 23:29  [ТС] 16
Всем большое спасибо за ответы.
В целом, предыстория вопроса такова. Такая конструкция используется для моделирования последовательности объектов конвейерного типа. v_ref - это входные данные в узел, полученные от предыдущего узла, v - выходное данные текущего узла, полученные как результат обработки v_ref. Таким образом, самый первый узел в очереди не имеет v_ref как результат работы предыдущего узла, т.е. ни на что не ссылается и не обрабатывается. Дело в том, что приведенный в начале темы код писался не мной. Лично я бы написал нечто подобное:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Base
{
public:
    Base(Base *instance, 
         unsigned int NumElems):
      vec(NumElems),
      vec_ref(instance==nullptr?  nullptr : &instance->vec)
    {}
    std::vector<float> vec;
    std::vector<float>* vec_ref;
};
 
class Der : public Base
{
public:
    Der() : Base(nullptr, 5){}
};
т.е. вместо ссылки был бы указатель - так понятнее. Но предыдущими разрабами реализовано именно через ссылку. Так вот я просто хотел выяснить, есть ли в этом какой-нибудь сакральный смысл, или это просто "индусский код"?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.07.2013, 23:32 17
Нет, это дешёвая русская подделка.
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 23:34  [ТС] 18
Цитата Сообщение от taras atavin Посмотреть сообщение
Нет, это дешёвая русская подделка.
Я Ваш юмор не очень понял.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
06.07.2013, 23:37 19
Ну настоящие индусы делают более тупые ошибки, так что это не индусский код, а очень кривая его русская имитация.
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 23:38  [ТС] 20
taras atavin, теперь понял)
0
06.07.2013, 23:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.07.2013, 23:38
Помогаю со студенческими работами здесь

Зачем нужны rvalue ссылки, если есть универсальные ссылки
Читаю книгу Скотта Мэйерса... Что-то я совсем запутался с этими rvalue ссылками. Я не пойму, зачем...

Загрузка файла на сервер, добавление в базу данных ссылки и вывод ссылки из базы
Добрый вечер. Изучаю php, появился вопрос, а решить уже дня 3 не могу своими силами, поэтому прошу...

Как достать ссылки из Memo1 в Memo2 ссылки только которые оканчиваются на *.jpg *.gif
mmo1.Lines.Text:= idhtp1.Get('http://m.vk.com/album138983341_195657842'); этот код показывает...

Ссылки с параметрами, Как передать параметры ссылки в javascript?
Реально ли получить значение гипперссылки? нужно передать клиенту, напр. если он передейдет по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru