Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
0 / 0 / 2
Регистрация: 04.07.2014
Сообщений: 93

Передача объекта по ссылке

26.07.2019, 09:12. Показов 5547. Ответов 45
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В книге Шилдта есть задание:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <cstring>
#include <cstdlib>
 
using namespace std;
 
class strtype
{
    char *p;
public:
    strtype(char *s);
    ~strtype() { delete [] p; cout << "Destruction\n"; }
    char* get() { return p; }
};
 
strtype::strtype(char *s)
{
    int l = 0;
    l = strlen(s) + 1;
 
    p = new char [l];
    if(!p) {
        cout << "Ошибка выделения памяти\n";
        exit(1);
    }
 
    strcpy(p, s);
}
 
void show(strtype x)  // правильно &x, то бишь передача по ссылке
{
    char *s;
 
    s = x.get();
    cout << s << "\n";
}
 
int main()
{
    strtype a("one"), b("two");
 
    show(a);
    show(b);
 
    return 0;
}
В ответе сказано : В исходной программе объект передается в функцию show() по значению. Поэтому делается его копияю
Когда функция show() возвращает свое значение, копия удаляется и при этом вызывается деструктор копии.
Это приводит к освобождению памяти, на которую указывает указатель р, но освобожденная память все еще необходима аргументам функции show().
Что означает, - освобожденная память все еще необходима... Разве у каждого объекта не свой указатель p. Объясните, пожалуйста, подробнее, что происходит на самом деле, почему в таком случае программа завершается критически?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.07.2019, 09:12
Ответы с готовыми решениями:

Передача объекта по ссылке
Не работает передача константы по ссылке. Ошибка: &quot;error: passing ‘const std::allocator&lt;int&gt;’ as ‘this’ argument discards qualifiers &quot;...

Передача объекта структуры по ссылке
Здравствуйте. Нужно использовать передачу структуры по ссылке(или по указателю). Объясните пожалуйста как это делать и , если можно, как...

Передача объекта-наследника по r-value ссылке на родительский класс
Здоровеньки булы. Собственно, код: class x { protected: int a; public: x() {} x(int i) : a(i) {} x(const x&amp;...

45
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
26.07.2019, 09:23
Цитата Сообщение от Валеронище Посмотреть сообщение
Что означает, - освобожденная память все еще необходима... Разве у каждого объекта не свой указатель p. Объясните, пожалуйста, подробнее, что происходит на самом деле, почему в таком случае программа завершается критически?
При копировании класса strtype сама строка строка p не копируется, копируется только указатель на эту строку. Т.е. при вызове show у тебя получаются два объекта, которые указывают на одну строку.
При выходе из функции один объект удаляется и удаляет в деструкторе это строку delete [] p. Однако, второй объект этого никак не знает и его p указывает на удалённую строку. При обращении к ней или попытке удаления возникает ошибка.
1
0 / 0 / 2
Регистрация: 04.07.2014
Сообщений: 93
26.07.2019, 12:25  [ТС]
Почему при вызове show получается два объекта?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
26.07.2019, 12:29
Цитата Сообщение от Валеронище Посмотреть сообщение
Почему при вызове show получается два объекта?
Цитата Сообщение от Валеронище Посмотреть сообщение
void show(strtype x) *// правильно &x, то бишь передача по ссылке
Потому, что когда ты передаёшь объект по значению (Т.е. без ссылки - &), то создаётся его копия.
1
0 / 0 / 2
Регистрация: 04.07.2014
Сообщений: 93
26.07.2019, 12:34  [ТС]
Хорошо, это понятно, но если убрать второй объект, то все работает, хотя ты так же передаешь объект по значению
C++
1
2
3
4
5
6
7
8
int main()
{
    strtype a("one");
 
    show(a);
 
    return 0;
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
26.07.2019, 12:46
Цитата Сообщение от Валеронище Посмотреть сообщение
Хорошо, это понятно, но если убрать второй объект, то все работает, хотя ты так же передаешь объект по значению
С чего ты взял? Точно также падает

Добавлено через 3 минуты
Ну да, в релизе почему то-не падает. Но это не важно, скорее всего случайно. По-любому так нельзя.
1
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
26.07.2019, 13:24
Цитата Сообщение от Валеронище Посмотреть сообщение
то все работает
Через n-ое количество запусков начнёт точно так же падать. Обращения к невыделенной для программы памяти обнаруживаются операционной системой не всегда.
1
0 / 0 / 2
Регистрация: 04.07.2014
Сообщений: 93
26.07.2019, 14:20  [ТС]
Сейчас вызвал ее в цикле сто раз, ни разу не упала ��

Добавлено через 1 минуту
Но правда вместо one, после первого раза, потом выводится черточка, так как память удалилась

Добавлено через 1 минуту
А когда два разных объекта, - сразу падает

Добавлено через 6 минут
И все же непонятна фраза "Это приводит к освобождению памяти, на которую указывает указатель р, но освобожденная память все еще необходима аргументам функции show()". Каким образом она необходима аргументам, функция ведь завершилась?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
26.07.2019, 14:24
Цитата Сообщение от Валеронище Посмотреть сообщение
Сейчас вызвал ее в цикле сто раз, ни разу не упала ��
А ты выдели в этом цикле память под что-нибудь

Добавлено через 2 минуты
Цитата Сообщение от Валеронище Посмотреть сообщение
И все же непонятна фраза "Это приводит к освобождению памяти, на которую указывает указатель р, но освобожденная память все еще необходима аргументам функции show()". Каким образом она необходима аргументам, функция ведь завершилась?
Имеется ввиду аргумент, который ты передаёшь снаружи, в твоём случае - объект 'a' - с которого снимается копия
1
0 / 0 / 2
Регистрация: 04.07.2014
Сообщений: 93
26.07.2019, 14:34  [ТС]
То есть по значению вообще не рекомендуется передавать объекты?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
26.07.2019, 14:39
Цитата Сообщение от Валеронище Посмотреть сообщение
То есть по значению вообще не рекомендуется передавать объекты?
Рекомендуется не копировать большие объекты без необходимости.

И делать для таких объектов, как у тебя, конструктор/оператор копирования.

Добавлено через 1 минуту
Здесь же нужно сделать
C++
1
2
void show(const strtype &x)  // правильно &x, то бишь передача по ссылке
{
Добавлено через 1 минуту
C++
1
2
3
4
5
6
class strtype
{
    char *p;
public:
    strtype(const char *s);
   strtype(const strtype &src) {new char.............................}
1
 Аватар для Krokodil9798
330 / 145 / 56
Регистрация: 17.10.2015
Сообщений: 580
26.07.2019, 14:42
Цитата Сообщение от Валеронище Посмотреть сообщение
C++
1
strtype::strtype(char *s)
Цитата Сообщение от Валеронище Посмотреть сообщение
C++
1
strtype a("one"), b("two");
Подобное вообще не скомпилится, так как идёт попытка инициализировать неконстантный указатель временным значением.
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
27.07.2019, 00:37
Цитата Сообщение от Krokodil9798 Посмотреть сообщение
так как идёт попытка инициализировать неконстантный указатель временным значением.
Ну оно же не временное
У литерала статический класс хранения, он живет все время выполнения программы.
Ошибка будет из-за того, что литерал - это константный массив, а инициализируется указатель на неконстанту.
1
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
27.07.2019, 00:50
я кстати думал, почему мой любимй Стауструп так сказал.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9006 / 4707 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
27.07.2019, 02:07
Цитата Сообщение от DrOffset Посмотреть сообщение
Ошибка будет из-за того, что литерал - это константный массив, а инициализируется указатель на неконстанту.
Вроде должно прокатить. Этот грех из С тянется.

Добавлено через 10 минут
Валеронище, смысл действа в том, что при передаче по значению, конструктор копии запускается неявно. Поскольку вы не определили свой конструктор копии, то вызов функции использует конструктор копии предоставляемый по умолчанию. Этот кк (ка-ка шка) делает побитовую копию и следовательно для нового объекта новая строка не создаётся (как в вашем конструкторе принимающем указатель). Только адрес в указателе скопируется и всё. Получается 2 объекта с одной и той же строкой в динамической памяти. Когда запустятся два деструктора, второму уже нечего будет удалять, но он попытается. Это обычно хорошо не заканчивается. Про это всё нужно читать и думать. А для начала попередвать классы без выделения/освобождения дп. Просто в конструкторе/деструкторе cout<<"\nctor\n"; и cout<<"\ndtor\n"; и посмотереть разные варианты. Повозвращать созданные в функции значения можно тоже.
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
27.07.2019, 11:17
Цитата Сообщение от IGPIGP Посмотреть сообщение
Вроде должно прокатить.
Зависит от настроек компилятора. Предупреждение будет точно.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9006 / 4707 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
27.07.2019, 11:51
Цитата Сообщение от DrOffset Посмотреть сообщение
Зависит от настроек компилятора. Предупреждение будет точно.
Some Forbiddings Is Not An Error)
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
27.07.2019, 12:02
Цитата Сообщение от IGPIGP Посмотреть сообщение
Some Forbiddings Is Not An Error
C точки зрения языка - это ошибка, тем не менее.
Компиляторы могут делать любые допущения, но это не меняет факта
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9006 / 4707 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
27.07.2019, 13:04
Цитата Сообщение от DrOffset Посмотреть сообщение
C точки зрения языка - это ошибка, тем не менее.
Не видел, чтобы язык имел точку зрения. Язык вынужден с эти жить и я написал:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Этот грех из С тянется
Грех - поступок порицаемый, но не наказуемый (если в нём нет преступления). Компилятор порицает. Мы говорим об одном.
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
27.07.2019, 13:37
Цитата Сообщение от IGPIGP Посмотреть сообщение
Не видел, чтобы язык имел точку зрения.
http://eel.is/c++draft/diff.iso#diff.lex-3

Не смотря на то, что это информативная часть, а не нормативная, информация опирается на нормативные положения, которые касаются неявного снятия константности в общем случае.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Компилятор порицает. Мы говорим об одном.
Я последний раз говорил о языке. Начиная с C++11 этот случай НЕ допускает трактовок.

В C++03 об этом отдельно упоминалось, хотя и (говоря вашим языком) порицалось:
Цитата Сообщение от 4.2\2
A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to
char”; a wide string literal can be converted to an rvalue of type “pointer to wchar_t”. In either case,
the result is a pointer to the first element of the array. This conversion is considered only when there is an
explicit appropriate pointer target type, and not when there is a general need to convert from an lvalue to an
rvalue. [Note: this conversion is deprecated. See Annex D. ] For the purpose of ranking in overload resolution (13.3.3.1.1), this conversion is considered an array-to-pointer conversion followed by a qualification
conversion (4.4). [Example: "abc" is converted to “pointer to const char” as an array-to-pointer conversion, and then to “pointer to char” as a qualification conversion. ]
С С++11 ничего такого в стандарте нет. Поведение литералов в этом случае подчиняется общим правилам, которые запрещают такое преобразование.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.07.2019, 13:37
Помогаю со студенческими работами здесь

Передача по ссылке
В учебнике написано, что можно использовать функцию с левой стороны операции присваивания, если она возвращает ссылку. Например, так: ...

Передача по ссылке
Задание №8 из книги &quot;Объектно-ориентированное программирование в С++&quot;, 4-е издание, Роберт Лафоре, 2004г. В некоторых компьютерных...

Передача по ссылке
Здравствуйте. 1.typedef struct { MATRIXX_LENTA&lt;double&gt;* MATR; //Ленточная матрица } DATA_LENTA, *PDATA_LENTA; DWORD WINAPI...

Передача по ссылке
С помощью функции rand() округлить значение double и передать его по ссылке.

Обращение к методам объекта по ссылке на объект
Метод объекта возвращает значение одного из параметров объекта. Необходимо обратиться к методу объекта по ссылке на этот объект. Когда...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru