Почему указатель удаления не работает должным образом? - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть проблема, я создал указатель, используя int *w = new int;, и я хотел удалить его delete w; после регистра переключателя l oop. Однако я получаю ошибку, показанную на прикрепленном скриншоте. Что интересно, delete w; работает только до обращения указателя на адрес объекта в векторе: w = &products.at(i).inStock;. После этого я получаю ошибку. delete w; также работает, если я установлю w = NULL;, что не имеет смысла для меня. Пожалуйста, помогите.

vendingmachine.h

#pragma once
#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

using namespace std;
//all classes below using namespace std

class VendingMachine
{
public:

    string name;
    int inStock;
    double value; //in Product the value is price, in Money the value is value
    int index;

    void loadFromFile(string ftxt);
    virtual void display() = 0; //clear virtual function, that will ve overridden in both Money and Product classes
    void saveToFile(string ftxt);

};

торговый автомат. cpp

#pragma once
#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"vendingmachine.h"

using namespace std;
//all classes below using namespace std

void VendingMachine::loadFromFile(string ftxt)
{
    fstream file;
    file.open(ftxt, ios::in);

    if (file.good() == false)
    {
        cout << "Unable to load the file. Try again later." << endl;
        file.close();
        exit(0);
    }
    else
    {
        int indexLineNr = (index - 1) * 4 + 1;
        int currentLineNr = 1;
        string lineText; //text gathered from one line in the text file
        while (getline(file, lineText)) //read the file till there is anyhting to read
        {
            if (currentLineNr == indexLineNr)
            {
                name = lineText.substr(3);
            }
            if (currentLineNr == indexLineNr + 1)
            {
                inStock = stoi(lineText.substr(8));
            }
            if (currentLineNr == indexLineNr + 2)
            {
                value = stod(lineText.substr(7, 5));
            }
            if (currentLineNr == indexLineNr + 3)
            {

            }
            /*currentLineNr++;*/
            currentLineNr++;
        }

        file.close();
    }
}

void VendingMachine::saveToFile(string ftxt)
{
    fstream file;

    file.open(ftxt, ios::out | ios::app);

    file << index << ") " << name << endl
        << "Amount: " << inStock << endl;

    file.close();
}

money.h

#pragma once
#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"vendingmachine.h"

using namespace std;

//all classes below using namespace std

class Money : public VendingMachine
{
    string filename = "money.txt";

public:

    Money(int = 1, string = "Money", int = 0, double = 0.0);

    virtual void display();
    void saveMoneyToFile(string ftxt);
};

money. cpp

#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"money.h"

using namespace std;

//all classes below using namespace std

Money::Money(int id, string n, int a, double v) //index, name, inStock, value (value)
{
    index = id;
    name = n;
    inStock = a;
    value = v; //in Product the value is price, in Money the value is value
}

void Money::display()
{
    cout << index << ") " << name << endl
        << "Amount: " << inStock << endl
        << "Value: " << value << " PLN " << endl
        << endl;
}

void Money::saveMoneyToFile(string ftxt)
{
    VendingMachine::saveToFile(ftxt);
    fstream fadd;
    fadd.open(ftxt, ios::out | ios::app);
    fadd << "Value " << value << " PLN" << endl
        << endl;
    fadd.close();
}

products.h

#pragma once
#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"vendingmachine.h"

using namespace std;

//all classes below using namespace std

using namespace std;

class Product : public VendingMachine
{
    string filename = "products.txt";

public:
    Product(int = 1, string = "Product", int = MAX_PRODUCTS_STOCK, double = 0.0);

    virtual void display();
    void saveProductsToFile(string ftxt);
};

продуктов. cpp

#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"products.h"
//#include"vendingmachine.h"

using namespace std;

//all classes below using namespace std

Product::Product(int id, string n, int a, double v) //index, name, inStock, value (price)
{
    index = id;
    name = n;
    inStock = a;
    value = v; //in Product the value is price, in Money the value is value
}

void Product::display()
{
    cout << index << ") " << name << endl
        << "Amount: " << inStock << endl
        << "Price: " << value << " PLN " << endl
        << endl;
}

void Product::saveProductsToFile(string ftxt)
{
    VendingMachine::saveToFile(ftxt);
    fstream fadd;
    fadd.open(ftxt, ios::out | ios::app);
    fadd << "Price: " << value << " PLN" << endl
        << endl;
    fadd.close();
}

main. cpp

#define MAX_PRODUCTS_STOCK 10
#define FIVEBUCKS_DEFAULT_STOCK 1
#define TWOBUCKS_DEFAULT_STOCK 5
#define ONEBUCK_DEFAULT_STOCK 10
#define FIFTYPENNY_DEFAULT_STOCK 10
#define TWENTYPENNY_DEFAULT_STOCK 50
#define TENPENNY_DEFAULT_STOCK 100

#include<iostream>
#include<string>
#include<vector>
#include<fstream>

#include"vendingmachine.h"
#include"products.h"
#include"money.h"

using namespace std;

double userInput;
double cart;
bool ok = false;

void onDelete(string ftxt)
{
    fstream fdelete;
    fdelete.open(ftxt, ios::out | ios::trunc);
    fdelete.close();
}

int main()
{
    double* wskU;
    Product* wskP;
    Money* wskM;

    cout << "Would you like to come back to the default stock?" << endl
        << "1. Yes, restock all the products and money  2. No, i want to load previous state" << endl;

    cin >> userInput;
    wskU = &userInput;

    // making a vector of default Products
    vector<Product> products;
    for (int i = 0; i < 5; i++)
    {
        products.push_back(Product());
        wskP = &products.at(i);
        wskP->index = i + 1; //index is needed to know from which line in the textfile, new product's members start
        wskP = &products.at(i);
        wskP->loadFromFile("products.txt");
        //wskP->display(); // to check if it works
    }
    //making a vector of default Money
    vector<Money> money;
    for (int j = 0; j < 6; j++)
    {
        money.push_back(Money());
        wskM = &money.at(j);
        wskM->index = j + 1; //index is needed to know from which line in the textfile, new product's members start
        wskM = &money.at(j);
        wskM->loadFromFile("money.txt");
        //wskM->display(); // to check if it works
    }

    // askIfDefault

    int* w = new int;

    while (ok == false)
    {
        switch ((int)round(*wskU))
        {
            // if we want to come back to default stock, all of the products and money members are restored
        case 1:
        {
            /*cout << "CASE 1 " << endl;*/
            for (int i = 0; i < 5; i++)
            {
                w = &products.at(i).inStock;
                *w = MAX_PRODUCTS_STOCK;
                //wskP = &products.at(i);
                //wskP->display();
            }

            w = &money.at(0).inStock;

            *w = FIVEBUCKS_DEFAULT_STOCK;
            /*wskM = &money.at(0);
            wskM->display();*/

            w = &money.at(1).inStock;
            *w = TWOBUCKS_DEFAULT_STOCK;
            /*wskM = &money.at(1);
            wskM->display();*/

            w = &money.at(2).inStock;
            *w = ONEBUCK_DEFAULT_STOCK;
            /*wskM = &money.at(2);
            wskM->display();*/

            w = &money.at(3).inStock;
            *w = FIFTYPENNY_DEFAULT_STOCK;
            /*wskM = &money.at(3);
            wskM->display();*/

            w = &money.at(4).inStock;
            *w = TWENTYPENNY_DEFAULT_STOCK;
            /*wskM = &money.at(4);
            wskM->display();*/

            w = &money.at(5).inStock;
            *w = TENPENNY_DEFAULT_STOCK;
            /*wskM = &money.at(5);
            wskM->display();*/

            cart = 0;
            /*w = NULL;*/
            ok = true;

        }
        break;

        // if we want to load the previous state 
        case 2:
        {
            /*cout << "CASE 2 " << endl;*/
                //wskP->display(); // to check if it works
            cart = 0;
            /*w = NULL;*/
            ok = true;

        }
        break;
        default:
        {
            cout << "Choose one either 1st or 2nd option: " << endl;
        }
        }
    }

    delete w;

    cout << endl << "How may I help you ?" << endl
        << "Choose one of the available products: " << endl
        << endl;

    for (int i = 0; i < 5; i++)
    {
        wskP = &products.at(i);
        wskP->display();
    }
    cout << "6) Go to checkout" << endl << endl
        << "7) Exit" << endl << endl;

    //cin >> userInput;
    //wskU = &userInput;


    //onDelete("products.txt");
    //for (int j = 0; j < 5;j++)
    //{
    //  wskP = &products[j];
    //  wskP->saveProductsToFile("products.txt");
    //}

    //onDelete("money.txt");
    //for (int j = 0; j < 5;j++)
    //{
    //  wskM = &money[j];
    //  wskM->saveMoneyToFile("money.txt");
    //}

    system("pause");
}

введите описание изображения здесь

1 Ответ

1 голос
/ 13 апреля 2020

В своем вопросе вы говорите, что «создали указатель, используя int *w = new int;», но вы сделали, что разместили новый int в куче и сохранили указатель на него в w . Затем вы изменяете этот указатель так, чтобы он указывал на переменную money.

Теперь фраза delete w скажет вашему компилятору попытаться удалить все, на что указывает указатель w . Чтобы было понятно, это не удаление самого указателя, а только памяти, на которую он указывает.

Из того, что я вижу (но я согласен с приведенным выше советом по созданию минимального воспроизводимого примера), вы можете просто выделите указатель в стеке следующим образом:

int *w;

Затем указатель автоматически удаляется, как только метод заканчивается, и для этого не нужно вызывать delete.

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

products.at(i).inStock = MAX_PRODUCTS_STOCK;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...