С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50

Глубокое копирование присваиванием по умолчанию? Как?

19.07.2019, 22:49. Показов 3431. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Встретил я в одной книге(Язык программирования С++. Лекции и упражнения) код(StringBad), в котором специально были сделаны ошибки. В данном коде был написан класс работающий с динамической памятью(соответственно были конструкторы с выделением динамической памяти и деструкторы с ее удалением), но не были определены копирующий конструктор и присваивание (генерировались копирующий и присваивание по умолчанию, то есть копирование памяти в них было поверхностное, вместо глубокого). Понятное дело, когда объект инициализировали другим объектом или проводили присваивание, происходили ляпы. Я решил исправить код сам и посмотреть, как исправил данный код автор книги. Но я добавил лишь копирующий конструктор(в тест коде, как я сказал, было еще и обычное присваивание). И все заработало нормально. Дело в том, что при присваивании не сработал ни какой из конструкторов(отсюда вывод - вызвалась функция присваивания по умолчанию). В деструкторах и конструкторах я написал код, который выводит адрес удаляемой строки(в данном случае, т.к. при присваивании не вызывался конструктор, надо смотреть на деструктор). Пусть , объект который присвоили "другому объекту" - N1, "другой объект" - N5. Так вот, адрес строки объекта N1 был отличен от адреса строки N5 (то есть, по логике, функция присваивания по умолчанию провел глубокое копирование?). Как?
Вот, кстати код: strnbad.h(в данном заголовке не только объявления, но и определения, то есть для него нету .cpp)
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// strngbad.h -- flawed string class definition
#include <iostream>
#ifndef STRNGBAD_H_
#define STRNGBAD_H_
#define _CRT_SECURE_NO_WARNINGS
class StringBad
{
private:
    char * str;                // pointer to string
    int len;                   // length of string
    static int num_strings;    // number of objects
public:
    StringBad(const StringBad&);
    StringBad(const char * s); // constructor
    StringBad();               // default constructor
    ~StringBad();              // destructor
// friend function
    friend std::ostream & operator<<(std::ostream & os, 
                       const StringBad & st);
};
#include <cstring>                    // string.h for some
using std::cout;
// initializing static class member
int StringBad::num_strings = 0;
// class methods
// construct StringBad from C string
StringBad::StringBad(const char * s)
{
    len = std::strlen(s);             // set size
    str = new char[len + 1];          // allot storage
    std::strcpy(str, s);              // initialize pointer
    num_strings++;                    // set object count
    cout << num_strings << ": \"" << str
        << "\" object created";    // For Your Information
    cout << "; address str " << &str << "\n";
}
StringBad::StringBad()                // default constructor
{
    len = 4;
    str = new char[4];
    std::strcpy(str, "C++");          // default string
    num_strings++;
    cout << num_strings << ": \"" << str
        << "\" default object created";  // FYI
    cout << "; address str " << &str << "\n";
}
StringBad::StringBad(const StringBad&sb)//copy constructor
{
    this->len = sb.len;
    str = new char[len + 1];
    std::strcpy(str, sb.str);
    num_strings++;
    cout << num_strings << ": \"" << str
        << "\" object created by copy constructor";    // For Your Information
    cout << "; address str " << &str << "\n";
}
StringBad::~StringBad()               // necessary destructor
{
    cout << "\"" << str << "\" object deleted, ";    // FYI
    --num_strings;                    // required
    cout << num_strings << " left"; // FYI
    cout << "; address str " << &str << "\n";
    delete[] str;                    // required
}
std::ostream & operator<<(std::ostream & os, const StringBad & st)
{
    os << st.str;
    return os;
}
#endif
А вот тест код данного класса(vegnews.cpp):
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
using std::cout;
#include "strngbad.h"
 
void callme1(StringBad &);  // pass by reference
void callme2(StringBad);    // pass by value
 
int main()
{
    using std::endl;
    {
        cout << "Starting an inner block.\n";
        StringBad headline1("Celery Stalks at Midnight");
        StringBad headline2("Lettuce Prey");
        StringBad sports("Spinach Leaves Bowl for Dollars");
        cout << "headline1: " << headline1 << endl;
        cout << "headline2: " << headline2 << endl;
        cout << "sports: " << sports << endl;
        callme1(headline1);
        cout << "headline1: " << headline1 << endl;
        callme2(headline2);
        cout << "headline2: " << headline2 << endl;
        cout << "Initialize one object to another:\n";
        StringBad sailor = sports;
        cout << "sailor: " << sailor << endl;
        cout << "Assign one object to another:\n";
        StringBad knot;
        knot = headline1;
        cout << "knot: " << knot << endl; 
        cout << "Exiting the block.\n";
    }
    cout << "End of main()\n";
    std::cin.get();
    return 0;
}
 
void callme1(StringBad & rsb)
{
    cout << "String passed by reference:\n";
    cout << "    \"" << rsb << "\"\n";
}
 
void callme2(StringBad sb)
{
    cout << "String passed by value:\n";
    cout << "    \"" << sb << "\"\n";
}
Миниатюры
Глубокое копирование присваиванием по умолчанию? Как?  
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.07.2019, 22:49
Ответы с готовыми решениями:

Как выполнять глубокое копирование объектов?
Вообщем возникла проблема при копирование объектов. Перешёл с С++ на питон. Появилась необходимость скопировать объект. В С++ для таких...

Глубокое копирование
Суть проста. Нужно скопировать массив ,включая вложенные массивы и объекты. Реализовать то реализовал. Да вот только смущает меня подобный...

Глубокое копирование объектов с интерфейсами
Подскажите пожалуйста, если класс наследует интерфейсы, то как реализовать его глубокое копирование. Проблема в том что в интерфейсах не...

8
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
19.07.2019, 22:57
Лучший ответ Сообщение было отмечено Dimgo2 как решение

Решение

Dimgo2, Вы выводите не адрес массива символов, а адрес указателя(поля класса) на этот массив, естественно он уникален для каждого экземпляра. Попробуйте заменить cout << &str на cout << (void*)str
1
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50
19.07.2019, 23:02  [ТС]
Были идеи, что создается временный объект, который инициализируется с помощью копирующего конструктора(то есть, происходит глубокое копирование в временный объект, его указатель(строка) указывается на динамическую память), а затем с помощью присваивания по умолчанию происходит почленное копирование. Но вызова копирующего конструктора в командном окне не видно(он печатает инфу о себе).
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50
19.07.2019, 23:09  [ТС]
Да, реально. Но почему Visual Studio выдает ошибку , а от него же компилятор через командную строку нет(плюс еще выводит удаленную строку)
Миниатюры
Глубокое копирование присваиванием по умолчанию? Как?  
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
19.07.2019, 23:20
Цитата Сообщение от Dimgo2 Посмотреть сообщение
Но почему Visual Studio выдает ошибку , а от него же компилятор через командную строку нет
О какой именно ошибке речь?
Цитата Сообщение от Dimgo2 Посмотреть сообщение
плюс еще выводит удаленную строку
Ну так строку никто не удалял, оператор delete[] "возвращает" занятую ей память обратно в кучу, обращение к этой памяти после этого - UB. Просто никто не затер её содержимое на момент этого обращения
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50
20.07.2019, 23:13  [ТС]
zayats80888Одно изображение(с ошибкой) от Visual Studio, другое изображение от компилятора Visual Studio, cl.exe . Это один и тот же код.
Миниатюры
Глубокое копирование присваиванием по умолчанию? Как?   Глубокое копирование присваиванием по умолчанию? Как?  
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50
20.07.2019, 23:15  [ТС]
fff
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
20.07.2019, 23:25
Ну так в первом случае вы его под дебагером запускаете
1
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 50
20.07.2019, 23:26  [ТС]
Поняв, спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.07.2019, 23:26
Помогаю со студенческими работами здесь

Глубокое копирование пользовательского элемента управления
Здравствуйте! Ну вопрос практически описан в шапке. Есть пользовательский контрол. Надо сделать его глубокую копию. Поскольку это...

Как сделать значение по умолчанию для параметра, если оно должно быть значением по умолчанию для типа T?
Как сделать значение по умолчанию для параметра, если оно должно быть значением по умолчанию для типа T? Module Program Sub Method(Of...

Классика - глубокое проникновение
Время от времени мы сталкиваемся с музыкой и исполнителями, которые потрясают наше сознание выходом за рамки обычного восприятия,...

Select из бд с присваиванием
переменной $test1 не присваивается число по запросу $query = 'SELECT `num0` FROM `id_question` WHERE `id` = 2'; ...

Сложности с присваиванием
Доброго времени суток! Подскажите, как решить проблему с присваиванием значения std::string в int. // testsss.cpp : Defines...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru