Первоначально моя лаборатория передавала три аргумента: 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;
}
У вас проблемы с управлением памятью.
Я предполагаю, что вы используете какую-то версию 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()
, который удаляет его.