1 / 1 / 1
Регистрация: 31.12.2016
Сообщений: 8
1

Работа с памятью

02.02.2017, 20:09. Показов 1399. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Форумчане, доброго времени суток.
Заранее извиняюсь за нубские вопросы, но должен разобраться в теме.

Суть такова: написал class String, в нем реализовал метод превращения двух строк в одну. Попутно ради практики использовал указатель this, и вроде понял, для чего он нужен - для того, чтобы компилятор не путал аргументы, передаваемые в метод и то, что находится в полях класса (поправьте, если ошибаюсь). Непосредственно вопрос: У меня в коде 2 раза выделяется память, освобождается же 1, в деструкторе прописана команда. Так и должно быть, или это не норма? Если норма - прошу объяснить почему. Так же буду крайне признателен за конструктивную критику кода и самой реализации.

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
71
72
73
74
75
#include <iostream>
#include <cstring>
using namespace std;
 
 
class String
{
    private:
        char *str;
        int size;
    public:
        String();
        String(char *str);
        char* append(char *str); //Метод, объединяющий две строки в одну
        ~String();
};
 
String::String()
{
    str = NULL;
    size = 0;
    //cout << "Сработал конструктор по умолчанию." << endl;
}
 
String::String(char *str)
{
    size = strlen(str);
    this->str = new char[size]; //Выделяем память
    for(int i(0); i < size; i++)
    {
        this->str[i] = str[i];
    }
    //cout << "Сработал конструктор с параметром." << endl;
}
 
char* String::append(char *str)
{
    char *buff = new char[size];
    for(int i(0); i < size; i++)
    {
        buff[i] = this->str[i];
    }
    
    int n = size;
    size = size + strlen(str);
    this->str = new char[size]; //Выделяем память второй раз
    
    for(int i(0); i < n; i++)
    {
        this->str[i] = buff[i];
    }
    
    for(int i(0); i < size; i++)
    {
        this->str[i + n] = str[i];
    }
    
    delete []buff;
 
    return this->str;
}
 
String::~String()
{
    delete []str;   //освобождаем
    //cout << "Сработал деструктор" << endl;
}
 
int main()
{
    
    setlocale(LC_ALL,"rus");
    String str_1("Hello, ");
    cout << str_1.append("World!");
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.02.2017, 20:09
Ответы с готовыми решениями:

Работа с памятью
Всем доброго времени суток. Почитав данный форум и проч. пришёл к выводу, что мой проект на C#...

работа с памятью
a) Статическая память. Двумерный массив. Дан массив целых чисел. В массиве есть отрицательные...

Работа с памятью
Есть приложение,в нем есть label'ы. Есть ли какая-нибудь возможность средствами C++ допустим,...

Работа с памятью
Всем привет! Не могу разобраться, как написать код программы, которая моделирует механизм...

3
1272 / 1029 / 470
Регистрация: 25.12.2016
Сообщений: 3,333
02.02.2017, 21:24 2
Цитата Сообщение от unylkun Посмотреть сообщение
У меня в коде 2 раза выделяется память, освобождается же 1, в деструкторе прописана команда.
Я вижу два вызова delete: в 58 и 65 строках.
Цитата Сообщение от unylkun Посмотреть сообщение
Так же буду крайне признателен за конструктивную критику кода и самой реализации.
На сколько я вижу, в конце строки не хранится нулевой байт. А значит, выдавать такую строку во внешний мир бессмысленно/небезопасно. В частности, в 74 строке кроме "Hello, world!" будет напечатан какой-то мусор.
Поэтому лучше потратить лишний байт и записать в него признак конца строки.
1
1 / 1 / 1
Регистрация: 31.12.2016
Сообщений: 8
02.02.2017, 23:40  [ТС] 3
Значит я не совсем правильно выразился, память выделяется еще в 38 строке, получается 3 раза. Я просто не акцентировал на этом внимание, т.к освобождается она сразу в этом методе. Интересует переменная str, для неё я выделил память в 28 и 46 строках. Потом она освобождается в деструкторе один раз. Это норма?))

За замечание спасибо.

UPD: Нулевой байт нужно добавить в вызов метода .append в 74 строке? (Присобачить его к World?) К слову, когда компилировал код, выводилась только строка, никакого мусора
0
1272 / 1029 / 470
Регистрация: 25.12.2016
Сообщений: 3,333
03.02.2017, 11:27 4
Лучший ответ Сообщение было отмечено unylkun как решение

Решение

Цитата Сообщение от unylkun Посмотреть сообщение
память выделяется еще в 38 строке, получается 3 раза
Действительно, что-то я не заметил в первый раз, невнимательно смотрел.
Теперь заметил, что в 46 строке будет утечка памяти: мы меняем указатель this->str, не удалив память, на которую он указывал.

Цитата Сообщение от unylkun Посмотреть сообщение
выводилась только строка, никакого мусора
Тут уж как повезёт. Если в конце программы добавить строку cout << str_1.append(" Another string.");, то у меня программа вообще падает.

Привожу свою реализацию, не меняющую интерфейс класса:
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
#include <iostream>
#include <cstring>
 
using namespace std;
 
class String
{
private:
    char *str;
    size_t size;
 
public:
    String();
    String(char *s);
    char* append(char *s); //Метод, объединяющий две строки в одну
    ~String();
};
 
String::String() : str(nullptr), size(0)
{
}
 
String::String(char *s)
{
    size = strlen(s);
    str = new char[size+1]; //Выделяем память
    // копируем s -> str, включая нулевой байт
    memcpy(str, s, size+1);
}
 
char* String::append(char *s)
{
    size_t n1 = size, n2 = strlen(s);
    char *newStr = new char[n1+n2+1];
 
    memcpy(newStr, str, n1);
    memcpy(newStr+n1, s, n2+1);
    size = n1+n2;
 
    delete[] str;
    return str = newStr;
}
 
String::~String()
{
    delete[] str;   //освобождаем
}
 
int main()
{
    setlocale(LC_ALL,"rus");
    String str_1("Hello, ");
    cout << str_1.append("World!") << endl;
    cout << str_1.append(" Another string.") << endl;
}
0
03.02.2017, 11:27
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.02.2017, 11:27
Помогаю со студенческими работами здесь

Работа с памятью
Добрый день всем. Я только начал изучение C#(раньше работал c: C++ маленько -т.е. общее...

Работа с памятью в С++
Здравствуйте. Если я правильно понимаю, то при запуске программы, программе выделяется определенное...

Работа с памятью
Может кто хорошо понимает механизм выделения и освобождения памяти объяснить его, а то я в конец...

Работа с памятью
Нужно ривести пример использования операторов new и delete для выделения памяти под двумерный...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru