оператор = перегрузка с двойными указателями для дробной математики

Первоначально моя лаборатория передавала три аргумента: addFractionJesseR (* lFrac, * rFrac, ** resFrac); но я только что узнал, что не могу передать три аргумента. Мне пришлось изменить его на ** resFrac = addFractionJesseR (* lFrac, * rFrac); и теперь у меня проблемы с компиляцией. Я знаю, что мои указатели и двойные указатели где-то находятся вне области видимости, но я просто не могу определить, где. отладчик указывает на вторую строку как проблему:

FractionJesseR& FractionJesseR::operator=(const FractionJesseR& arg) {
num = arg.num;
denom = arg.denom;
return *this;
}

который вызывается:

FractionJesseR& addMenu(FractionJesseR* lFrac, FractionJesseR* rFrac) {
int option;
FractionJesseR** resFrac = new FractionJesseR*();
......
case 2:
cout << "Calling add() --\n\n";
**resFrac = addFractionJesseR(*lFrac, *rFrac);
break;
......

** resFrac = addFractionJesseR (* lFrac, * rFrac); изначально был addFractionJesseR (* lFrac, * rFrac, ** resFrac);

который вызывается:

void displayMenu() {
int option;
FractionJesseR *lFrac = nullptr;
FractionJesseR *rFrac = nullptr;
FractionJesseR *resFrac = nullptr;
......
case 2:
cout << "  Adding Option --\n\n";
if (lFrac == nullptr && rFrac == nullptr) {
cout << "    Not a proper call as no Fractions are available!\n\n";
}
else {
*resFrac = addMenu(lFrac, rFrac);
}
break;

* resFrac = addMenu (lFrac, rFrac) изначально был addMenu (lFrac, rFrac, &resFrac)

(да, я вызывал delete для всех моих указателей, я все еще новичок в Stack Overflow и учусь выводить только соответствующие фрагменты кода) Мне нужна помощь, чтобы направить меня в правильном направлении. Я думаю, что мои указатели выходят за рамки где-то в addMenu или displayMenu … может быть, я разыменовываю двойной указатель неправильно?

Любая помощь будет принята с благодарностью!

редактировать:

FractionJesseR& addFractionJesseR(FractionJesseR& lFrac, FractionJesseR& rFrac) {
int n = 0;
int d = 0;
FractionJesseR *resFrac = nullptr;

// Adding the fractions
n = (&lFrac)->getNum() * (&rFrac)->getDenom() + (&lFrac)->getDenom() *
(&rFrac)->getNum();
d = (&lFrac)->getDenom() * (&rFrac)->getDenom();

resFrac = new FractionJesseR(n / gcd(n, d), d / gcd(n, d));

if (d < 0) {
d = -d;
n = -n;
}

return *resFrac;
}

0

Решение

У вас проблемы с управлением памятью.

Я предполагаю, что вы используете какую-то версию Visual Studio. Отладчик обычно помечает следующую строку для выполнения, поэтому вы получаете сбой на

num = arg.num;

Это происходит потому, что this является нулевым, так как

FractionJesseR** resFrac = new FractionJesseR*();

размещает указатель на бесплатное хранилище (что необычно) и инициализирует его 0 (из-за скобок). Это:

**resFrac

первые разыменования resFrac, давая нулевой указатель, который вы потом разыменовываете снова. Разыменование нулевого указателя является неопределенным поведением. В вашем случае это вызывает сбой в операторе присваивания в первом операторе.

Очевидное решение — перестать использовать указатели и ручное управление памятью. В лучшем случае используйте объекты:

FractionJesseR resFrac
// ...
resFrac = addFractionJesseR(*lFrac, *rFrac);

В худшем случае используйте умные указатели:

auto resFrac = std::make_unique<FractionJesseR>();
// ...
*resFrac = addFractionJesseR(*lFrac, *rFrac);

Что вы не хотите делать (если вы не обязаны это делать, потому что это задание, в таком случае я бы поставил под сомнение мотивацию):

auto resFrac = new FractionJesseR;
// ...
*resFrac = addFractionJesseR(*lFrac, *rFrac);
// ...
delete resFrac;

addFractionJesseR() возвращает ссылку на значение, которое было размещено в бесплатном магазине. Где вы собираетесь удалить его? каждый new должны быть сопоставлены с delete,

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

FractionJesseR* addFractionJesseR(FractionJesseR* a, FractionJesseR* b)
{
auto n = a->getNum() * b->getDenom() + a->getDenom() * b->getNum();
auto d = a->getDenom() * b->getDenom();

if (d < 0)
{
d = -d;
n = -n;
}

return new FractionJesseR(n / gcd(n, d), d / gcd(n, d));
}

FractionJesseR* addMenu(FractionJesseR* a, FractionJesseR* b)
{
// ...
FractionJesseR* resFrac = addFractionJesseR(a, b);
// ...
return resFrac;
}

void displayMenu()
{
// ...
FractionJesseR *resFrac = addMenu(lFrac, rFrac);
// ...
delete resFrac;
}

Обратите внимание, что указатель расположен в addFractionJesseR() возвращается addMenu(), который возвращает его displayMenu(), который удаляет его.

1

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


По вопросам рекламы [email protected]