Выделение памяти из закрытой переменной класса

#include <stdio.h>
#include <iostream>
#include <string>using namespace std;

class myClass{

public:
int *num1;
myClass();};

myClass::myClass(){
num1 = new int[1];
num1[0] = 10;
}int main()
{
myClass *myclass;

myclass = new myClass[10];

cout << myclass[0].num1[0] << endl;

delete &myclass[0];
cout << myclass[0].num1[0] << endl;

}

Я хочу удалить первый экземпляр myclass (myclass [0]).

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

Что я сделал не так?

1

Решение

Создайте функцию внутри вашего класса, которая обрабатывает удаление его закрытых членов, может быть вызвана FreeMem(int index)

void myClass::FreeMem()
{
delete [] num1
}

Но, честно говоря, освобождение памяти объекта без использования деструктора в такого рода программах является опасной и прямо-таки плохой практикой. Я бы порекомендовал освободить память в вашем деструкторе, поэтому, когда объект завершается, он освобождает память,

myClass::~myClass()
{
delete [] num1;
}

Еще одна вещь, на которую следует обратить внимание: если вы создаете только одно значение в вашей динамической переменной, было бы проще записать его как:

int * pnum = new int;
//or in your class..
pnum = new int;

среди прочего, у вас есть много недостатков в вашей программе. Я бы порекомендовал перечитать на уроках снова.

1

Другие решения

Вы не можете удалить только часть массива, созданного с new, new выделяет блок памяти, который может быть только deleteвсе вместе

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

Если вы хотите, чтобы меньший блок памяти содержал выделенный вами массив, вы должны выделить меньший блок и переместить содержимое, которое вы хотите сохранить, в новый блок, а затем удалить весь старый блок:

int *arr = new int[10];

int *tmp = new int[9];
std::copy(arr+1, arr+10, tmp);
delete [] arr;
arr = tmp;

Вам нужно спроектировать свой класс, чтобы управлять его собственными ресурсами, а также обрабатывать копирование или перемещение. Ваш текущий myClass выделяет массив, но полагается на другой код для очистки. Это не очень хороший способ сделать это, потому что часто никакой другой код не в состоянии сделать правильную вещь, и даже когда вы можете, вы очень часто будете делать ошибки.

Поскольку вы размещаете в конструкторе, вам нужен деструктор, который обрабатывает освобождение. И затем, поскольку вы реализуете одну из трех специальных операций (copy-ctor, copy-assignment, destructor), вам необходимо рассмотреть возможность их реализации. (Это называется «Правило трех». В C ++ 11 оно становится «Правилом пяти» с добавлением Move-ctors и назначением ходов.)

class myClass {
public:
myClass();

// destructor to handle destroying internal resources correctly
~myClass();

// copy constructor and copy assignment operator, to handle copying correctly
myClass(myClass const &rhs);
myClass &operator=(myClass const &rhs);

// move constructor and move assignment operator, to handle moves correctly (C++11)
myClass(myClass && rhs);
myClass &operator= (myClass &&rhs);

private:
int *num1; // private so external code can't screw it up

public:
// limited access to num1
int size() const { if (num1) return 1; else return 0; }
int &operator[] (size_t i) { return num1[i]; }
};

Вы можете реализовать конструктор так же, как вы, или использовать список инициализаторов и унифицированную инициализацию C ++ 11:

myClass::myClass() : num1(new int[1]{10}) {}

Теперь требуемый деструктор зависит от семантики, которую должен иметь класс, и от конкретных инвариантов, которые вы хотите поддерживать. Семантика ‘value’ является нормой в C ++ (если вы знакомы с Java или C #, эти языки поощряют или требуют семантику ‘reference’ для пользовательских типов). Вот деструктор, который вы можете использовать, если вам нужна семантика значений, и если вы поддерживаете инвариант, которому num1 всегда принадлежит память или он равен нулю.

myClass::~myClass() { delete num1; }

Копирование и перемещение могут быть обработаны различными способами. Если вы хотите полностью запретить их, вы можете сказать (в C ++ 11):

myClass::myClass(myClass const &rhs) = delete;
myClass &myClass::operator=(myClass const &rhs) = delete;

myClass::myClass(myClass && rhs) = delete;
myClass &myClass::operator= (myClass &&rhs) = delete;

Или, если вы хотите разрешить копирование и / или перемещение (и сохранить семантику значений и инвариант, упомянутый выше), вы можете реализовать одну или обе эти пары функций:

myClass::myClass(myClass const &rhs) : num1( rhs.size() ? new int[1]{rhs[0]} : nullptr) {}
myClass &myClass::operator=(myClass const &rhs) {
if (num1)
num1[0] = rhs[0];
}

myClass::myClass(myClass && rhs) : num1(rhs.num1) { rhs.num1 = nullptr; } // remember to maintain the invariant that num1 owns the thing it points at, and since raw pointers don't handle shared ownership only one thing can own the int, and therefore only one myClass may point at it. rhs.num1 must be made to point at something else...
myClass &myClass::operator= (myClass &&rhs) { std::swap(num1, rhs.num1); } // steal rhs.num1 and leave it to rhs to destroy our own num1 if necessary. We could also destroy it ourselves if we wanted to.

С помощью этой реализации вы теперь можете обрабатывать объект myClass так же, как int или любой другой тип значения. Вам больше не нужно беспокоиться об управлении своими внутренними ресурсами; он позаботится о них сам.

int main() {
std::vector<myClass> myclassvec(10);

cout << myclassvec[0][0] << '\n';

myclassvec.erase(myclassvec.begin()); // erase the first element

cout << myclassvec[0][0] << '\n'; // access the new first element (previously the second element);
}
2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector