Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
#1

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

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

Доброго времени суток.
Рассмотрим вот такой код:
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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2013, 22:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Интересная инициализация ссылки (C++):

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

Интересная головоломка - C++
1.С помощью текстового редактора создать файл который содержит текст.Длина ряда с текстом не должна превышать 80 символов.Это входной файл....

Интересная сортировка - C++
Помогите пожалуйста с задачкой,если можно с комментариями Ввести матрицу и провести сортировку всех столбцов следующим...

Интересная сортировка - C++
Добрый день . Увидел задачу не могу решить :cry::-| какой час уже . Вообщем есть массив : Вот 3 2 7 5 6 7 После того как 7 (то есть х )...

Интересная задача - C++
Добрый вечер! если не трудно можете мне помочь с решение задания Шарик бросают в интересное устройство, схематично представлен на...

Интересная задачка - C++
#include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; int main() { double z1,z2; double a,b,c,d,s,t,u; ...

19
DU
1483 / 1129 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:09 #2
это код с неопределенным поведением и скорее всего крашем.
синтаксически все верно. но в рантайме начнутся проблемы, т.к. тут попытка обратится к члену какого-то объекта через нулевой указатель.
1
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:11  [ТС] #3
DU, lда, это я уже проверил - дамп памяти получился. но если не обращаться к этому элементу, то все вроде бы ок. я вот хотел бы уточнить, не чревато ли это утечками какими-нибудь, если код оставить как есть, но не обращаться к элементу vec_ref, инициализированному как показано выше?
0
Kastaneda
Jesus loves me
Эксперт С++
4688 / 2892 / 236
Регистрация: 12.12.2009
Сообщений: 7,354
Записей в блоге: 2
Завершенные тесты: 1
06.07.2013, 22:12 #4
Цитата Сообщение от Gorillych Посмотреть сообщение
ссылка ведь не может быть NULL как указатель
Нет, так и в коде этого тоже нет.
Цитата Сообщение от Gorillych Посмотреть сообщение
Получается, что в конструкторе Base происходит нечто вроде nullptr->vec.
Ну да, ссылка на вектор инициализируется вектором. Что не так?
Цитата Сообщение от Gorillych Посмотреть сообщение
насколько безопасен такой код?
Не на сколько, он же в рантайме сломается
0
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:14  [ТС] #5
Цитата Сообщение от Kastaneda Посмотреть сообщение
Не на сколько, он же в рантайме сломается
сломается, только если к этой ссылке обратиться
0
Kastaneda
Jesus loves me
Эксперт С++
4688 / 2892 / 236
Регистрация: 12.12.2009
Сообщений: 7,354
Записей в блоге: 2
Завершенные тесты: 1
06.07.2013, 22:17 #6
Цитата Сообщение от Gorillych Посмотреть сообщение
сломается, только если к этой ссылке обратиться
а nullptr->vec не смущает?
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
06.07.2013, 22:17 #7
Gorillych, Ссылка безопаснее лишь тем, что не может быть не инициализированной, но никто не запрещает инмциализировать ее не верными данными
0
DU
1483 / 1129 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
06.07.2013, 22:19 #8
ну есть негласное правило, когда лучше ссылки использовать, а когда указатели.
если ваш класс может корректно работать в случае, когда ему передадут нулевой указатель (типа специально предусмотрена такая возможность для какого-нибудь там дефолтного поведения) - то передаем в него указатель.
если не может (в вашем случае - не может. т.к. внутренний член инициализируется членом, получаемым от переданного в конструктор объекта), то тут лучше воспользоваться ссылкой, т.к. ссылки вроде как как всегда ссылаются на какой-то объект. "вроде как" - это не всегда так, но в этом случае ответственность на вызывающей стороне. она должна следить, чтобы в конструктор приходила ссылка на существующий объект. т.о., использование ссылки вместо указателя намекает вызывающей стороне что сюда нужно отдавать что-то существующее, иначе сам дурак.
0
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
06.07.2013, 22:34  [ТС] #9
Croessmah, жаль, лучше бы уж компилятор ругался в таких случаях

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

Добавлено через 3 минуты
DU, если vec_ref будет не ссылкой, а указателем, от этого что-то принципиально изменится в рантайме?
0
Kastaneda
Jesus loves me
Эксперт С++
4688 / 2892 / 236
Регистрация: 12.12.2009
Сообщений: 7,354
Записей в блоге: 2
Завершенные тесты: 1
06.07.2013, 22:38 #10
Цитата Сообщение от Gorillych Посмотреть сообщение
смущает, конечно) поэтому и тему создал
Так оно сломается в момент обращения по nullptr, т.е. еще до инициализации ссылки.

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

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

P.S. хотя замечание в целом верное, я что-то неподумав написал.
0
DU
1483 / 1129 / 45
Регистрация: 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
Kastaneda
Jesus loves me
Эксперт С++
4688 / 2892 / 236
Регистрация: 12.12.2009
Сообщений: 7,354
Записей в блоге: 2
Завершенные тесты: 1
06.07.2013, 22:56 #14
Цитата Сообщение от DU Посмотреть сообщение
а вот при попытке изменить obj за счет вызова какого-нибудь метода или просто изменить. если это какой-нибудь инт, вот тут будут проблемы, т.к. obj указывает хз куда.
Да, верно. Вот это
Цитата Сообщение от Kastaneda Посмотреть сообщение
но винда и линукс на х86 выкинут исключение.
я писал опять не думая У меня в голове картина по другому выглядела (там почему-то было obj = *(0 + offset))
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
06.07.2013, 23:00 #15
Цитата Сообщение от Gorillych Посмотреть сообщение
ссылка ведь не может быть NULL как указатель.
Может. Но стать NULL она не может, а только быть изначально. И поменяться может только NULL ссылка.
0
06.07.2013, 23:00
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2013, 23:00
Привет! Вот еще темы с ответами:

Интересная сортировка - C++
Дан вектор.Сжать существующий вектор,удалив все отрицательные элементы,не используя дополнительный вектор. Огромная,просьба...

Интересная штука - C++
Интересная штука происходит. Создал я значит сетевое приложение, ну естественно подключена ws2_32.lib. Так вот, даже закомпилированная в...

Интересная конструкция в C++ - C++
Добрый день. Подскажите пожалуйста, что это такое: float time = clock.getElapsedTime().asMicroseconds();

интересная головоломка - C++
помоготе решить задачу про спички я уже неделю голову ломаю....Даны n-спичек и 2 игрока,каждый может вытянуть от 1 до 3 спичек...выигрывает...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru