Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

WasteOfRAM avatar WasteOfRAM 5 Точки

Task 2 Register of Three

Кода минава тестовете но преминава memory лимита. Няма memory leaks мисля предполагам че проблема ми е в assignment  оператора но не мога да намеря друг начин да го направя.

 

#include "Register.h"

Register::Register(size_t numCompanies)
{
	numAdded = numCompanies;
	companiesArray = new Company[numCompanies];
}

void Register::add(const Company& c)
{
	static int index = 0;
	companiesArray[index] = c;
	++index;
	if (index == numAdded)
	{
		for (size_t i = 0; i < numAdded; i++)
		{
			--index;
		}
	}
}

Company Register::get(int companyId) const
{
	for (size_t i = 0; i < numAdded; i++)
	{
		if (companiesArray[i].getId() == companyId)
		{
			return companiesArray[i];
			break;
		}
	}
}

Register& Register::operator=(const Register& other)
{
	if (this != &other)
	{
		this->numAdded = other.numAdded;
		this->companiesArray = new Company[this->numAdded];
		*this->companiesArray = *other.companiesArray;
	}
	
	return *this;
}

Register::Register(const Register& other)
	:numAdded(other.numAdded),companiesArray(other.companiesArray)
{

}

Register::~Register()
{
	delete[] companiesArray;
	companiesArray = nullptr;
}

 

Тагове:
0
C++ Advanced
galin_kostadinov avatar galin_kostadinov 166 Точки
Best Answer

Привет!

 

1. Register::Register(size_t numCompanies){...}

numAdded = 0; тази стойност ти отговаря на колко компании си добавил в масива, а не на големината на масива. В този конструктор само заделяме памет за някакъв брой компании, но все още не сме добавили такива.

 

2. void Register::add(const Company& c){...}

Тук numAdded се използва като индекс на който да добавиш дадената компания.

Тъй като в Register.h не е заложено size, а от друга страна в RegisterMain.cpp се поверява дали сме достигнали до капацитета на масива, то не е нужно да правиш проверки дали не си достигнал size преди да добавиш новият елемент.

 

3. Company Register::get(int companyId) const{...}

Тук задължително трябва да върнеш променлива, в случая обект от тип Company. Тъй като имаш само if то ако не влезе там не се знае какво ще върне като резултат от този метод. Поради това след цъкала добави и return Company(); ако искаш може да зададеш и да ти е с недействителен, невъзможен id за компания, примерно -1, но и така ще ти свърши работа, както съм го написал. След return няма смисъл от break.

 

4. Register& Register::operator=(const Register& other){...}

Тук имаш memory leak. Не си освободил старата памет, ако преди това е заделена такава.

Примерен вариант как да подходиш:

if (this != &other) {
    if (this->companiesArray != nullptr) {
        delete[] this->companiesArray;
    }

    this->numAdded = other.numAdded;
    this->companiesArray = new Company[other.numAdded];

    int arrSize = (size_t) other.numAdded;
    for (int i = 0; i < arrSize; ++i) {
        this->companiesArray[i] = other.companiesArray[i];
    }
}

 

5. Register::Register(const Register& other){...}

Company* companiesArray - това е променлива от тип пойнтър, което ще рече, че съхнанява едно число, което само по себе си е обикновена size_t стойност(цяло число без знаково), но то отговаря номера на адреса на дадена клетка в RAM-та - клетаката от която започва заделената динамично памет на масива в other.

Така както си го направил ти даваш това число на настоящият обект, който създаваш или с други думи при дереференциране на other или на this(настоящият обект) ще достъпват една и съща памет, т.е. споделят обща референция. Проблеме е, че когато единия излезе извън неговия скоуп, то ще се извика деструктора му и ще освободи тази памет. След това и другия обект ще излезе извън скоуп и на него щу му се викне деструктора и ще каже освободи ми същата памет. Имаш недефенирано поведение тук - едно, че ще освобождаваш два пъти една и съща памет, но също така може да пробваш да достъпиш освободената памет, чрез някой от обектите ти, който все още не е излязал извън скоупа си.

Решението е подобно на точка 4, като няма памет за осбождаване, тъй като сега създаваш новия обект.

 

Поздрави!

1
01/02/2020 23:22:53
WasteOfRAM avatar WasteOfRAM 5 Точки

Проблема е че надвишавам memory лимита с около 1.5MB. Откъде ми идва повечето RAM ме интересува.

1. Аз това съм направил доколкото виждам. Ако е грешно и заделям повече от необходимото ако може да ме насочиш.

2. Не намерих начин как да ползвам numAdded за индекс. Този if не проверява края за да добавя елементи прави друго. Може да е гешно но е мого ясно каква му е функцията.

3. Това го опеавих но така като гледам не ми идват от там тези 1.5MB RAM заради който не ми минава решението.

0
galin_kostadinov avatar galin_kostadinov 166 Точки

Привет!

Понеже беше доста дълго за писанe, ти го пуснах на порции и може да не си го видял цялото. Виж точка 4 за проблема с надвишената памет.

Eто така си създаваш обект от тип Register, както съм обяснил в точка 1: numAdded го мисли като индекс, той е различен за всеки един обект от тип Register:

Register::Register(size_t numCompanies) : numAdded(0), companiesArray(new Company[numCompanies]) {}
void Register::add(const Company &c) {
    this->companiesArray[this->numAdded] = c;
    this->numAdded++;
}

Поздрави!

0
02/02/2020 10:22:17
WasteOfRAM avatar WasteOfRAM 5 Точки

Да получи се с промяната на точка 4. Докато тествах го пусках да направи 9999999 повторения и рамта не помръдваше. Трябва да се мисли повече какво откаде идва и каде отива. Въобще не се сетих че this е вече инициализирано и е заделена памет при създаване. Благодаря.

0
j.petrov_90 avatar j.petrov_90 373 Точки

Привет, колега WasteOfRAM

galin_kostadinov много точно те е насочил към проблема.

Аз реално нямам какво смислено да добавя ...
просто искам да отбележа, че грешката при теста за RAM памет е много тематична с ник-а ти :D

Живи и здрави
 

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.