Другое > Hard'n'Soft
Програмирование на C++
<< < (11/25) > >>
HoRRoR:

--- Код: ---Понятно. То есть эффективность в основном  в условной компиляции.

--- Конец кода ---
Да как бы сказать... это единственный способ условной компиляции. Ну если не считать шаблоны за условную компиляцию. Так что о эффективности можно не говорить.


--- Код: ---Ато что-то я в преподше моей по с++ разочаровался

--- Конец кода ---
Да с преподавателями вообще беда. Они в основном теоретики и зачитывают наизусть заученные тексты, многое не понимая и постоянно делая ляпы. Наша преподавательница работала программистом C#, но читала курс C++. Постоянно делала ляпы, не знала что такое GNU GCC, т.е. ни с чем, кроме студии, не работала. Сначала с ней спорил, думая, что она действительно так считает. А оказывается она просто толком ничего не знает :D


--- Код: ---а выделение памяти через maloc, а удаление через delete (хотя это я уже придираюсь) ...

--- Конец кода ---
Да нет, это грубая ошибка. Всё зависит от реализации, конечно, но обычно используются разные методы для выделения памяти, следовательно - разные механизмы её высвобождения. Т.е. в реализациях с разными механизмами гарантирована в лучшем случае утечка памяти.
Вообще советую new использовать для объектов (тем более, что он вызывает конструктор) и массивов переменных, а malloc/calloc - для обычных данных (графика, например, или буфер - в общем, не переменные).
gepar:
А когда я делаю конструктор для инициализации элемента класса элементом другого класса (композиция) то получается я обязан делать и конструктор по умолчанию (хотя бы пустой ничего не делающий с {}) иначе в main я не смогу создать новый объект моего класса не передавая ничего, ну не смогу написать:
myclass a;
почему так? Ведь не делай я конструктор на случай если я потом захочу присвоить объекту myclass a значение другого класса то я спокойно могу сделать в main
myclass a;
и никаких пустых конструкторов по умолчанию при этом делать не надо, почему так? Опять стандарт?
Собственно пример если я непонятно выразился (пример из конспекта преподши, просто решил переделать от скуки чтобы можно было инициализировать объект одного класса значениями другого, сам пример изначально наоборот демонстрировал что этого делать нельзя  :) ) :

--- Код: ---#include<iostream>
using namespace std;
class myclass
{
public:
int a,b;
void set(int i, int j){a = i;b=j;}
void show() { cout<< a <<' ' << b << "\n"; }
};
class yourclass
{
int a,b;
public:
void set(int i, int j){a = i;b=j;}
yourclass(){};                                         //Без этого не получиться создать в main yourclass o2 не передавая параметров в скобках
yourclass(myclass &abc) {a=abc.a;b=abc.b;}
void show() { cout<< a <<' '<< b << "\n"; }
};
int main()
{
myclass o1; yourclass o2;
o1.set(10,4);
o2=o1;
o1.show();
o2.show();
return 0;
}

--- Конец кода ---
Все мелочи неточности и что нежелательно делать в этом примере, а было сделано давайте опустим  :)

Добавлено позже:
Ну и заодно вопрос: можно ли объявить другом (friend) класса другой класс подскажите пожалуйста? Ну на случай что мне надо будет чтобы функции одного класса могли обращаться к приватным данным другого класса, я так догадываюсь это вполне реально ведь :) Я ведь пока знаю только как объявить функцию-друга класса только если эта функция будет за границей классов вообще.

Добавлено позже:
Вопрос N3: у преподши повсюду идёт проверка что память через malloc/new была выделена, это пережитки прошлого (когда оп было мало) чтоль или это хороший тон, хотя на последнее не очень то похоже. Это если бы я выделял память в большом объёме тогда ладно, но когда массив из 10 int объектов что не займёт много памяти то по-моему эта проверка лишняя ... или нет?
HoRRoR:

--- Цитата ---почему так?
--- Конец цитаты ---
Потому что если не описывать ни одного конструктора, то он будет создан автоматически - с пустым телом и без параметров, называется конструктор по умолчанию. А иначе ты сам описываешь конструкторы и можешь создавать объекты только с существующими конструкторами. Т.е. при наличии хоть одного конструктора не будет создаваться пустой конструктор по умолчанию.


--- Цитата ---можно ли объявить другом (friend) класса другой класс подскажите пожалуйста?
--- Конец цитаты ---
А что мешало тебе проверить? Написать внутри класса friend class MyClass? Конечно можно.


--- Цитата ---Вопрос N3
--- Конец цитаты ---
Поясни, я о такой проверке не слышал, не приходилось использовать.
А разницы в объёме нет - хоть один байт, хоть гигабайт - это выделенный блок памяти, так что не лишняя. Лишняя она если ты знаешь, где какой метод выделения памяти ты используешь и у тебя гарантированно не случается накладок.
gepar:

--- Цитата: HoRRoR ---Т.е. при наличии хоть одного конструктора не будет создаваться пустой конструктор по умолчанию.
--- Конец цитаты ---
Ага, теперь понятно.

--- Цитата: HoRRoR ---А что мешало тебе проверить? Написать внутри класса friend class MyClass? Конечно можно.
--- Конец цитаты ---
Да ничего не мешало, не знал я как это сделать, пробовал писать просто friend MyClass, а компилятор сказал что так нельзя ну я и решил спросить. Теперь понятно, спасибо за ответ  :)

--- Цитата: HoRRoR ---оясни, я о такой проверке не слышал, не приходилось использовать.
--- Конец цитаты ---
Ну у неё всюду
p=new char[1];
if(!p) {cout << "Ошибка выделения памяти \n"; exit(1);}
Помоему задолбаться можно это приписывать при каждом выделении памяти.

Добавлено позже:
Вопрос на засыпку: а как удалить структуру (ну что мне писать в деструкторе в классе) ?
Есть вот такая структура в классе  и вот мой деструктор, который тоже в классе:

--- Код: ---    struct PRICE
    {
        char name[30];// название товара
        char shop[30];//;// название магазина
        double cost;// цена товара
    };
    PRICE abc;

    ~Test()
    {
        cout<<"Дестуктор был запущен";
        delete abc.cost;
        delete abc.name;
        delete abc.shop;
    }

--- Конец кода ---
Я так понимаю это я плохо придумал, но просто удалить структуру не получается (ну оно и не удивительно  :) ), а если пробовать удалять по кускам то double элемент структуры удаляться не хочет с ошибкой:
||In destructor `Test::~Test()':|
|27|error: type `double' argument given to `delete', expected pointer|
Так всё же как в таких случаях поступать?
HoRRoR:

--- Цитата ---Ну у неё всюду
--- Конец цитаты ---
Тю блин, ты про это... Я думал, ты про проверку, выделена память через new или через malloc. Честно - я никогда не использую, но вообще осторожность лишней не бывает.


--- Цитата ---Вопрос на засыпку: а как удалить структуру (ну что мне писать в деструкторе в классе) ?
--- Конец цитаты ---
Эээ... А ничего, что удалять можно только выделенные блоки памяти? о_О Причём только через указатель, полученный при выделении. А ты пытаешься кусок памяти внутри выделенного куска (и то при условии, что объект Test у тебя создаётся через new), да ещё и передавая не указатели, а переменные о_О Вообще глупость, в общем... Чтобы удалить структуру, ты сперва должен её создать сам.
gepar:
HoRRoR,ну у меня тут по умолчанию вместе с классом всегда создаётся и структура abc (PRICE abc) под которую и выделяется там место - два массива по 30 элементов и один элемет double, допустим что их инициализацию мы тоже провели и её то (структуру) теперь и надо удалить так как больше из данных класс ничего не имеет, ну static элементы есть, но они общие. Как мне поступить посоветуй. Я понял что я пробую глупо её удалить, но как тогда иначе поступить?
HoRRoR:
Зачем тебе её удалять? В чём смысл? При удалении объекта класса она сама удалится. В твоём примере ты пытаешься удалить её в деструкторе, что вообще лишено смысла - после деструктора она сама удалится.
А если уж действительно накладно её хранить - то создавай и удаляй её сам:

--- Код: ---PRICE *abc;
Test()
{
    abc = new PRICE;
}
void foo()
{
    ...
    delete abc;
    ...
}

--- Конец кода ---
gepar:
HoRRoR,а я с самого начала так попробовал, пишет
\7\4.cpp||In destructor `Test::~Test()':|
\7\4.cpp|27|error: type `struct Test::PRICE' argument given to `delete', expected pointer|
У меня же сейчас опять же таки важно не то чтобы это было красиво /логично/удобно, а то чтобы в программе был деструктор  :)
Это как и с той же структурой запихнутой в класс - непонятно зачем, но надо. Вот и здесь так, я там дальше тоже извращался с конструктором по умолчанию чтобы он хоть что-то делал лишь бы он был.
На всякий случай код программы полностью:

--- Код: ---//Программа создаёт структру, запрашивает данные для её заполнения после
//чего производит поиск по структуре введённых данных

# include <iostream>
# include <iomanip>
# include <windows.h>
using namespace std;

const int size=3;

class Test
{
public:
    Test()
    {
        numberOfClass++;
    }

    Test(Test &right)
    {
        abc=right.abc;
    }

    ~Test()
    {
        cout<<"Дестуктор был запущен";
        delete abc;
    }

    void setName(char a[])
    {
        strcpy(abc.name,a);
    }

    void setShop(char a[])
    {
        strcpy(abc.shop,a);
    }

    char *getShop()
    {
        return abc.shop;
    }

    void setCost(double a)
    {
        if (a>0)
         abc.cost=a;
        else
        {
            cout<<"Введена направильная цена, цена установлена в 1\n";
            abc.cost=1;
        }
    }


    void search(char a[]) // Ищет есть ли в структуре элементы с нужным нам именем
    {
        if (!(strcmp(a,abc.name)))
        {
            cout<<"Нужный вам товар есть в магазине  "<<abc.shop
            <<"\nЕго цена составляет: "<<abc.cost<<" грн"<<"\n\n";
            resultOfSeach=1;
        };
    }

    static int searchs()
    {
        return resultOfSeach;//Возвращает результат поисков
    }

    static int numberOfClass;
private:
    struct PRICE
    {
        char name[30];// название товара
        char shop[30];//;// название магазина
        double cost;// цена товара
    };
    PRICE abc;
    static int resultOfSeach;// Нужна чтобы знать был ли найден товар для хоть одного класса
};

int Test::resultOfSeach=0;
int Test::numberOfClass=0;


int main()
{
    setlocale(LC_ALL, "Russian");
    char search[30];
    char temp[30];
    int result=0;
    double cost;
    int n;
    cout<<"Введите колличество магазинов: ";
    cin>>n;
    Test *a=new Test [n];
    for (int i=0;i<n;i++)
    {
        cout<<"-----Магазин N"<<i+1<<"-----\n";
        cout<<"Введите название товара: ";
        cin>>temp;
        a[i].setName(temp);
        cout<<"Введите название магазина:";
        cin>>temp;
        a[i].setShop(temp);
        cout<<"Введите цену товара :";
        cin>>cost;
        a[i].setCost(cost);
    }
    cout<<"\nВведите имя интересущего вас товара: ";
    cin>>search;
    for (int i=0;i<n;i++)
     a[i].search(search);
    if (!(a[0].searchs()))
     cout<<"Указанный товар в магазинах не найден\n";
    Test b=a[0];
    delete a;
    cout<<"\nКонструктор копии работает и мы можем увидеть название магазина N1\nдаже после удаления оригинала a: "<<b.getShop()<<'\n';
    cout<<"Всего было магазинов: "<<Test::numberOfClass<<'\n';
    system("pause");
    return EXIT_SUCCESS;
}

--- Конец кода ---
Вообще можешь и не читать полнсотью, надо только чтобы деструктор удалил саму структуру.
HoRRoR:

--- Цитата ---HoRRoR,а я с самого начала так попробовал, пишет
--- Конец цитаты ---
Перечитай ещё раз мой код и вчитайся в текст ошибки. Ты не так пробовал.

И вообще, глупость неимоверная - париться насчёт удаления текстуры, которая создаётся и удаляется автоматически.
gepar:
HoRRoR,перечитал и всё равно не могу уловить твою идею. Ну пытаюсь сделать конструктор как у тебя и тогда получаю
\7\4.cpp||In constructor `Test::Test()':|
\7\4.cpp|16|error: no match for 'operator=' in '((Test*)this)->Test::abc = (Test::PRICE*)operator new(72u)'|
\7\4.cpp|77|note: candidates are: Test::PRICE& Test::PRICE::operator=(const Test::PRICE&)|
Какая-то страшная ошибка.
HoRRoR:
Да твою мать, перечитай ещё раз! Указатель там, а не структура! new может возвращать только указатель.
gepar:
HoRRoR, не сердись  :) Там просто другая проблема возникает (ну помимо того что надо всюду делать операцию стрелка) с контруктором копии...
если оставить всё как есть в прошлом коде то тогда он будет указывать на тот же участок памяти (ну и при повторном удалении конечно же будет ошибка), хотя я уже  исправил и теперь программа выглядит так:

--- Код: ---//Программа создаёт структру, запрашивает данные для её заполнения после
//чего производит поиск по структуре введённых данных

# include <iostream>
# include <iomanip>
# include <windows.h>
using namespace std;

const int size=3;

class Test
{
public:
    Test()
    {
        abc = new PRICE;
        numberOfClass++;
    }

    Test(Test &right)
    {
        abc= new PRICE;
        strcpy(abc->name,right.abc->name);
        strcpy(abc->shop,right.abc->shop);
        abc->cost=right.abc->cost;
    }

    ~Test()
    {
        cout<<"Дестуктор был запущен";
        delete abc;
    }

    void setName(char a[])
    {
        strcpy(abc->name,a);
    }

    void setShop(char a[])
    {
        strcpy(abc->shop,a);
    }

    char *getShop()
    {
        return abc->shop;
    }

    void setCost(double a)
    {
        if (a>0)
         abc->cost=a;
        else
        {
            cout<<"Введена направильная цена, цена установлена в 1\n";
            abc->cost=1;
        }
    }


    void search(char a[]) // Ищет есть ли в структуре элементы с нужным нам именем
    {
        if (!(strcmp(a,abc->name)))
        {
            cout<<"Нужный вам товар есть в магазине  "<<abc->shop
            <<"\nЕго цена составляет: "<<abc->cost<<" грн"<<"\n\n";
            resultOfSeach=1;
        };
    }

    static int searchs()
    {
        return resultOfSeach;//Возвращает результат поисков
    }

    static int numberOfClass;
private:
    struct PRICE
    {
        char name[30];// название товара
        char shop[30];//;// название магазина
        double cost;// цена товара
    };
    PRICE *abc;
    static int resultOfSeach;// Нужна чтобы знать был ли найден товар для хоть одного класса
};

int Test::resultOfSeach=0;
int Test::numberOfClass=0;


int main()
{
    setlocale(LC_ALL, "Russian");
    char search[30];
    char temp[30];
    int result=0;
    double cost;
    int n;
    cout<<"Введите колличество магазинов: ";
    cin>>n;
    Test *a=new Test [n];
    for (int i=0;i<n;i++)
    {
        cout<<"-----Магазин N"<<i+1<<"-----\n";
        cout<<"Введите название товара: ";
        cin>>temp;
        a[i].setName(temp);
        cout<<"Введите название магазина:";
        cin>>temp;
        a[i].setShop(temp);
        cout<<"Введите цену товара :";
        cin>>cost;
        a[i].setCost(cost);
    }
    cout<<"\nВведите имя интересущего вас товара: ";
    cin>>search;
    for (int i=0;i<n;i++)
     a[i].search(search);
    if (!(a[0].searchs()))
     cout<<"Указанный товар в магазинах не найден\n";
    Test b=a[0];
    delete a;
    cout<<"\nКонструктор копии работает и мы можем увидеть название магазина N1\nдаже после удаления оригинала a: "<<b.getShop()<<'\n';
    cout<<"Всего было магазинов: "<<Test::numberOfClass<<'\n';
    system("pause");
    return EXIT_SUCCESS;
}

--- Конец кода ---
ТЕ: в конструкторе копии я через strcpy построчно копирую все данные из одной структуры в другую, жаль что нельзя посредством присваивания как-то указать что нужно скопировать все данные из тех участков памяти, а не указывать на тот же участок.
HoRRoR:

--- Цитата ---Там просто другая проблема возникает (ну помимо того что надо всюду делать операцию стрелка)

--- Конец цитаты ---
А необходимость набирать код для тебя не проблема?


--- Цитата ---если оставить всё как есть в прошлом коде то тогда он будет указывать на тот же участок памяти (ну и при повторном удалении конечно же будет ошибка)

--- Конец цитаты ---
А что тебе мешает написать конструктор копии, в котором ты будешь нормально создавать копию?


--- Цитата ---жаль что нельзя посредством присваивания как-то указать что нужно скопировать все данные из тех участков памяти, а не указывать на тот же участок.
--- Конец цитаты ---
Можно. Структура скопируется полностью как надо, т.к. память здесь не выделяемая, а фиксированная.
gepar:

--- Цитата: HoRRoR ---А что тебе мешает написать конструктор копии, в котором ты будешь нормально создавать копию?
--- Конец цитаты ---
Так я же и написал его:

--- Код: ---    Test(Test &right)
    {
        abc= new PRICE;
        strcpy(abc->name,right.abc->name);
        strcpy(abc->shop,right.abc->shop);
        abc->cost=right.abc->cost;
    }
--- Конец кода ---

--- Цитата: HoRRoR ---Можно. Структура скопируется полностью как надо, т.к. память здесь не выделяемая, а фиксированная.
--- Конец цитаты ---
Нет, ну я же переделал по твоему совету чтобы был указатель abc (ну чтобы деструктору было чем заняться  :) ) так что память теперь выделяемая.

Хотя там программа то уже как видишь работает и в ней всё ок, а вот теперь мне надо переделать ту где динамическая структура (та которая двунаправленный список), вот в ней то и начинается всё интересное.
Просто эта динам. структура (я ещё тогда переделал твой вариант вытянув все функции из структуры в класс и поправив указатели, в структуре лишь оставил конструктор по умолчанию) ведёт себя слегка странно.
 Вариант 1 всё работает хорошо:

--- Код: ---#include <iostream>
#include <cstring>
using namespace std;


class Test
{
public:
    struct ListItem;

    // Конструктор по умолчанию
    Test(string data)
    {
        abc=new ListItem(data);
    }



// Печать списка
void print_list()
{
    ListItem* item = this->abc;
    while(item)
    {
        cout << item->data;
        item = item->next;
        if(item) cout << " ";
    }
    cout << endl;
}

// Удаляет первые символы в строках
void assigned()
{
    ListItem* item=this->abc;
    while (item)
    {
        item->data.assign(&item->data[1]);
        item=item->next;
    }
}

//Добавляет инвертированный список
void plus_invert ()
{
    ListItem *item=this->getTail();
    while (item)
    {
        this->addToTail(item->data);
        item = item->prev;
    }
}


    ListItem* getTail()
    {
        ListItem* item = abc;
        while(item->next)
            item = item->next;
        return item;
    }

    ListItem* addToTail(const string data)
    {
        ListItem *item = new ListItem(data), *last = getTail();
        item->prev = last;
        last->next = item;
        return item;
    }

    ListItem* findLastItem(const string data)
    {
        ListItem* item = abc, *last = NULL;
        while(item->next)
        {
            if(item->data == data)
            {
                last = item;
            }
            item = item->next;
        }
        return last;

    }
    bool insertAfterLastItem(const string data, Test list)
    {
        ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last;
        if(!last) return false;
        next_item = last->next;
        list_last = getTail();
        list_last->next = next_item;
        if(next_item)
            next_item->prev = list_last;
        list.abc->prev = last;
        last->next = list.abc;
        return true;
    }
struct ListItem
{
    string data;       // Хранимые в элементе списка данные
    ListItem *prev, *next;  // Указатели на предыдущий и следующий элементы

    // Конструктор
    ListItem(const string data):prev(NULL),next(NULL)
    {
        this->data = data;
    }

    ~ListItem()
    {
        if(next) delete next;
    }
};
 ListItem *abc;
};




int main()
{
    Test a("aa1");
    a.addToTail("aa2");
    a.addToTail("aa3");
    a.addToTail("aa4");
    cout << "List a: ";
    a.print_list();


    Test b("bb1");
    b.addToTail("bb2");
    b.addToTail("bb3");
    b.addToTail("bb4");
    cout << "List b: ";
    b.print_list();

    a.insertAfterLastItem("aa3", b);
    cout << "Merged: ";
    a.print_list();
    a.assigned();
    cout<<"After deleting first symbol: ";
    a.print_list();
    a.plus_invert();
    cout<<"After inverting (and append): ";
    a.print_list();
    return 0;
}


--- Конец кода ---

И тут я добавляю деструктор  что удаляет мой указатель abc на структру ...

--- Код: ---#include <iostream>
#include <cstring>
using namespace std;


class Test
{
public:
    struct ListItem;

    // Конструктор по умолчанию
    Test(string data)
    {
        abc=new ListItem(data);
    }

    ~Test()
    {
        cout<<"Destructor runs";
        delete abc;
    }

// Печать списка
void print_list()
{
    ListItem* item = this->abc;
    while(item)
    {
        cout << item->data;
        item = item->next;
        if(item) cout << " ";
    }
    cout << endl;
}

// Удаляет первые символы в строках
void assigned()
{
    ListItem* item=this->abc;
    while (item)
    {
        item->data.assign(&item->data[1]);
        item=item->next;
    }
}

//Добавляет инвертированный список
void plus_invert ()
{
    ListItem *item=this->getTail();
    while (item)
    {
        this->addToTail(item->data);
        item = item->prev;
    }
}


    ListItem* getTail()
    {
        ListItem* item = abc;
        while(item->next)
            item = item->next;
        return item;
    }

    ListItem* addToTail(const string data)
    {
        ListItem *item = new ListItem(data), *last = getTail();
        item->prev = last;
        last->next = item;
        return item;
    }

    ListItem* findLastItem(const string data)
    {
        ListItem* item = abc, *last = NULL;
        while(item->next)
        {
            if(item->data == data)
            {
                last = item;
            }
            item = item->next;
        }
        return last;

    }
    bool insertAfterLastItem(const string data, Test list)
    {
        ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last;
        if(!last) return false;
        next_item = last->next;
        list_last = getTail();
        list_last->next = next_item;
        if(next_item)
            next_item->prev = list_last;
        list.abc->prev = last;
        last->next = list.abc;
        return true;
    }
struct ListItem
{
    string data;       // Хранимые в элементе списка данные
    ListItem *prev, *next;  // Указатели на предыдущий и следующий элементы

    // Конструктор
    ListItem(const string data):prev(NULL),next(NULL)
    {
        this->data = data;
    }

    ~ListItem()
    {
        if(next) delete next;
    }
};
 ListItem *abc;
};




int main()
{
    Test a("aa1");
    a.addToTail("aa2");
    a.addToTail("aa3");
    a.addToTail("aa4");
    cout << "List a: ";
    a.print_list();


    Test b("bb1");
    b.addToTail("bb2");
    b.addToTail("bb3");
    b.addToTail("bb4");
    cout << "List b: ";
    b.print_list();

    a.insertAfterLastItem("aa3", b);
    cout << "Merged: ";
    a.print_list();
    a.assigned();
    cout<<"After deleting first symbol: ";
    a.print_list();
    a.plus_invert();
    cout<<"After inverting (and append): ";
    a.print_list();
    return 0;
}


--- Конец кода ---
И получаю очень интересную картину...
Если честно то у меня разрыв шаблона: я всегда думал что программа при попытке обратиться к памяти где данные другой программы то получит отказ, а оно во как.

Добавлено позже:
Ну как я понимаю у меня что-то не так с insertAfterLastItem (после её работы здесь такое начинается), но почему без написания моего деструктора проблем нет мне непонятно. И в итоге непонятно с insertAfterLastItem что-то не так или с деструктором что-то не так.

Добавлено позже:
Такс, нашёл одну из ошибок (я балда амперсант не поставил и там передавалась копия этой insertAfterLastItem вместо оригинала), но теперь программа не доходит до конца и после запуска деструктора зависает, притом зависает не всегда, а в процентах 70%  o_0 Пытается освободить уже освобождённую память где-то чтоль? Так почему не каждый раз тогда зависает ...

--- Код: ---#include <iostream>
#include <cstring>
using namespace std;


class Test
{
public:
    struct ListItem;

    // Конструктор по умолчанию
    Test(string data)
    {

        abc=new ListItem(data);
    }

    ~Test()
    {
        cout<<"DESTRUCTOR RUNS\n";
        delete abc;
    }

// Печать списка
void print_list()
{
    ListItem* item = this->abc;
    while(item)
    {
        cout << item->data;
        item = item->next;
        if(item) cout << " ";
    }
    cout << endl;
}

// Удаляет первые символы в строках
void assigned()
{
    ListItem* item=this->abc;
    while (item)
    {
        item->data.assign(&item->data[1]);
        item=item->next;
    }
}

//Добавляет инвертированный список
void plus_invert ()
{
    ListItem *item=this->getTail();
    while (item)
    {
        this->addToTail(item->data);
        item = item->prev;
    }
}


    ListItem* getTail()
    {
        ListItem* item = abc;
        while(item->next)
            item = item->next;
        return item;
    }

    ListItem* addToTail(const string data)
    {
        ListItem *item = new ListItem(data), *last = getTail();
        item->prev = last;
        last->next = item;
        return item;
    }

    ListItem* findLastItem(const string data)
    {
        ListItem* item = abc, *last = NULL;
        while(item->next)
        {
            if(item->data == data)
            {
                last = item;
            }
            item = item->next;
        }
        return last;

    }
    bool insertAfterLastItem(const string data, Test &list)
    {
        ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last;
        if(!last) return false;
        next_item = last->next;
        list_last = getTail();
        list_last->next = next_item;
        if(next_item)
            next_item->prev = list_last;
        list.abc->prev = last;
        last->next = list.abc;
        return true;
    }
struct ListItem
{
    string data;       // Хранимые в элементе списка данные
    ListItem *prev, *next;  // Указатели на предыдущий и следующий элементы

    // Конструктор
    ListItem(const string data):prev(NULL),next(NULL)
    {
        this->data = data;
    }

    ~ListItem()
    {
        if(next) delete next;
    }
};
 ListItem *abc;
};




int main()
{
    Test a("aa1");
    a.addToTail("aa2");
    a.addToTail("aa3");
    a.addToTail("aa4");
    cout << "List a: ";
    a.print_list();


    Test b("bb1");
    b.addToTail("bb2");
    b.addToTail("bb3");
    b.addToTail("bb4");
    cout << "List b: ";
    b.print_list();

    a.insertAfterLastItem("aa3", b);
    cout << "Merged: ";
    a.print_list();
    a.assigned();
    cout<<"After deleting first symbol: ";
    a.print_list();
    a.plus_invert();
    cout<<"After inverting (and append): ";
    a.print_list();
    return 0;
}

--- Конец кода ---


Добавлено позже:
Да что же это такое, я же деструктор то оставил в самой структуре и ему заняться  нечем кроме как освобождения повторно памяти, во туплю сегодня.
HoRRoR:

--- Цитата ---Нет, ну я же переделал по твоему совету чтобы был указатель abc (ну чтобы деструктору было чем заняться   ) так что память теперь выделяемая.
--- Конец цитаты ---
Аргх!

--- Код: ---        abc= new PRICE;
        *abc = *(right.abc);

--- Конец кода ---


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

--- Конец цитаты ---
В смысле? Архитектура не даст тебе залезть в память другого приложения.
gepar:
HoRRoR,воот, а почему тогда уходил на печать список запущенных/установленных приложений, информация о процессоре  (я картинку убрал так как теперь по контексту не подходит, но могу ещё раз прикрепить если ты её не видел) ?

Добавлено позже:
Кстати финальный результат моей работы:

--- Код: ---#include <iostream>
#include <cstring>
using namespace std;


class Test
{
public:
    struct ListItem;

    // Конструктор по умолчанию
    Test(string data)
    {

        abc=new ListItem(data);
    }

    ~Test()
    {
        cout<<"DESTRUCTOR RUNS\n";
        delete abc;
    }

    Test(Test &right)
    {
        ListItem* item = right.abc;
        abc=new ListItem (item->data);
        item=item->next;
        while (item)
        {
            this->addToTail(item->data);
            item=item->next;
        }


    }

// Печать списка
void print_list()
{
    ListItem* item = this->abc;
    while(item)
    {
        cout << item->data;
        item = item->next;
        if(item) cout << " ";
    }
    cout << endl;
}

// Удаляет первые символы в строках
void assigned()
{
    ListItem* item=this->abc;
    while (item)
    {
        item->data.assign(&item->data[1]);
        item=item->next;
    }
}

//Добавляет инвертированный список
void plus_invert ()
{
    ListItem *item=this->getTail();
    while (item)
    {
        this->addToTail(item->data);
        item = item->prev;
    }
}


    ListItem* getTail()
    {
        ListItem* item = abc;
        while(item->next)
            item = item->next;
        return item;
    }

    ListItem* addToTail(const string data)
    {
        ListItem *item = new ListItem(data), *last = getTail();
        item->prev = last;
        last->next = item;
        return item;
    }

    ListItem* findLastItem(const string data)
    {
        ListItem* item = abc, *last = NULL;
        while(item->next)
        {
            if(item->data == data)
            {
                last = item;
            }
            item = item->next;
        }
        return last;

    }
    bool insertAfterLastItem(const string data, Test &list)
    {
        ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last;
        if(!last) return false;
        next_item = last->next;
        list_last = getTail();
        list_last->next = next_item;
        if(next_item)
            next_item->prev = list_last;
        list.abc->prev = last;
        last->next = list.abc;
        return true;
    }
struct ListItem
{
    string data;       // Хранимые в элементе списка данные
    ListItem *prev, *next;  // Указатели на предыдущий и следующий элементы

    // Конструктор
    ListItem(const string data):prev(NULL),next(NULL)
    {
        this->data = data;
    }
};
 ListItem *abc;
};




int main()
{
    Test *a=new Test("aa1");
    a->addToTail("aa2");
    a->addToTail("aa3");
    a->addToTail("aa4");
    cout << "List a: ";
    a->print_list();


    Test b("bb1");
    b.addToTail("bb2");
    b.addToTail("bb3");
    b.addToTail("bb4");
    cout << "List b: ";
    b.print_list();

    a->insertAfterLastItem("aa3", b);
    cout << "Merged: ";
    a->print_list();
    a->assigned();
    cout<<"After deleting first symbol: ";
    a->print_list();
    a->plus_invert();
    cout<<"After inverting (and append): ";
    a->print_list();
    Test c=*a;
    delete a;
    cout<<"After deleting a we still can see our elements,\nso constructor of copy work correct:\n";
    c.print_list();
    return 0;
}

--- Конец кода ---
Теперь уже вылетов и ситуаций когда программа иногда виснет за счёт того что освобождает уже освобождённую память нет  :)
DeniSS:
Это открытый урок? :D
gepar:
DeniSS,ага. HoRRoR лекции читает, у него это хорошо получается  :)
HoRRoR:

--- Цитата ---HoRRoR,воот, а почему тогда уходил на печать список запущенных/установленных приложений, информация о процессоре  (я картинку убрал так как теперь по контексту не подходит, но могу ещё раз прикрепить если ты её не видел) ?
--- Конец цитаты ---
А хрен знает. Мусор, наверное. Т.е. выделяется память под приложение - естественно, она не очищается. Далее, ты сам либо забываешь заменить данные на свои, либо же вылезаешь за пределы - т.е. внутри выделенной под приложение памяти затрагиваешь не выделенные участки памяти, которые до этого не были использованы программой, т.е. данные в них остались старые. А в них может быть что угодно - т.е. любые данные работы предыдущих программ или системы.

Абстрактный пример - запустил ты программу, она записала в память "Hello World!". Закрыл программу, открыл твою - система распределила память так, что частично или полностью блок памяти, использовавшийся в первой программе, используется и в этой. В ней ты выделил память под строку, она волей случая совпала с началом "Hello World!". Далее у тебя какой-то сбой, при котором ты либо не туда пишешь свои данные, либо вовсе забываешь записать их в строку, но выводишь её. В результате, при выводе строки получаешь "Hello World!".
Или же ты записываешь данные в строку, но при выводе что-то путаешь (вылезаешь за пределы) и попадаешь на "Hello World!".
gepar:
Читаю о наследовании и возник вопрос:
вот есть у нас класс abc унаследовавший от xyz его функции, при этом в abc у нас есть функция void print() и в xyz у нас есть функция void print(). Есть main, которая тестирует наш новый класс abc и при вызове из main получается вызывается функция print() из abc, так? Если да то можно ли вызвать ту старую print() что была в xyz, ну мне так чисто интересно  :) ?
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии