Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > контейнер типа list


Автор: N20 5.1.2012, 02:23
Доброго времени суток. Помогите пожалуйста с такой задачей. Нужно создать контейнер типа лист в котором будут храниться указатели на объекты моего класса. Организовать добавление и вывод их на экран. Я столкнулся с проблемой, что при использовании данного кода во все объекты, начиная со ВТОРОГО, сохраняется одна и та же информация, при чем та что вводилась мною для последнего объекта. Пожалуйста, объясните почему так происходит, и помогите это исправить. Заранее благодарен.
Код

   int tmp=4;
   list<mr_string*> lst1;
   list<mr_string*>::iterator p;
   lst1.push_back(&mr_string());
    p = lst1.begin();
   (*p)->vvod();
   for(int i=0;i<(tmp);i++)
   {
      lst1.push_back(&mr_string());
      ++p;
      (*p)->vvod();
    }  
   p = lst1.begin();
   cout<< "konteyner nomer 1"<< endl;

   while (p!=lst1.end())
   {
      (*p)->vuvod();
      ++p;
   }

Автор: Cheloveck 5.1.2012, 16:26
Функция mr_string() возвращает объект в стеке, ты берёшь его адрес и пихаешь в лист. Естественно, что стек затерается. Для хранения списка указателей на объекты нужно хранить также и сами объекты, а ты их теряешь.

Автор: Cheloveck 5.1.2012, 17:11
Код

#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <memory>

class MyObject {
public:
    void Scan() {
        std::cin >> value;
    }

    void Print() const {
        std::cout << value;
    }

private:
    std::string value;
};

MyObject ** MakeBuffer(size_t size) {
    MyObject ** buffer = new MyObject * [size];
    ::memset(buffer, 0, sizeof(MyObject *) * size);
    return buffer;
}

void DropBuffer(MyObject ** buffer, size_t size) {
    std::for_each(&buffer[0], &buffer[size - 1], [](MyObject * obj) { 
        delete obj;
    });
    delete [] buffer;
}

int main() {
    const size_t size = 4;
    MyObject ** buffer = MakeBuffer(size);
    std::list<MyObject *> objects;

    for(size_t i = 0; i < size; ++i) {
        MyObject * obj = new MyObject();
        std::cout << "Type value for object number " << i << ": ";
        obj->Scan();
        buffer[i] = obj;
        objects.push_back(obj);
    }

    std::for_each(objects.begin(), objects.end(), [](MyObject * obj) { 
        obj->Print();
        std::cout << std::endl;
    });

    DropBuffer(buffer, size);

    ::system("PAUSE");
    return 0;
}

Как-то так. Лямбды и for_each можно заменить на старый добрый for по итераторам, если юзаешь C++ отличный от прошлогоднего стандарта.

Можно обойтись и без массива, тогда указатель в листе будет единственным на объект и его важно будет не потерять.
Код

#include <iostream>
#include <string>
#include <list>
#include <algorithm>

class MyObject {
public:
    void Scan() {
        std::cin >> value;
    }

    void Print() const {
        std::cout << value;
    }

private:
    std::string value;
};


int main() {
    const size_t size = 4;
    std::list<MyObject *> objects;

    for(size_t i = 0; i < size; ++i) {
        MyObject * obj = new MyObject();
        std::cout << "Type value for object number " << i << ": ";
        obj->Scan();
        objects.push_back(obj);
    }

    std::for_each(objects.begin(), objects.end(), [](MyObject * obj) { 
        obj->Print();
        std::cout << std::endl;
    });

    std::for_each(objects.begin(), objects.end(), [](MyObject * obj) { 
        delete obj;
    });

    ::system("PAUSE");
    return 0;
}


Если лямбды совсем не понятны, то второй вариант без них будет выглядить так
Код

#include <iostream>
#include <string>
#include <list>

class MyObject {
public:
    void Scan() {
        std::cin >> value;
    }

    void Print() const {
        std::cout << value;
    }

private:
    std::string value;
};


int main() {
    const size_t size = 4;
    std::list<MyObject *> objects;

    for(size_t i = 0; i < size; ++i) {
        MyObject * obj = new MyObject();
        std::cout << "Type value for object number " << i << ": ";
        obj->Scan();
        objects.push_back(obj);
    }

    for(std::list<MyObject *>::const_iterator it = objects.begin();
        objects.end() != it; ++it) {
            (*it)->Print();
            std::cout << std::endl;
    }

    for(std::list<MyObject *>::const_iterator it = objects.begin();
        objects.end() != it; ++it) {
            delete (*it);
    }

    ::system("PAUSE");
    return 0;
}


Если между последними двумя циклами ничего делать не нужно, их можно объединить.

Автор: N20 5.1.2012, 18:38
Спасбо большое, очень помогли.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)