Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

STL <vector>

1.9K
26 октября 2006 года
burst
94 / / 04.09.2006
есть класс someclass. объекты этого класса храняться в <vector>

делаю так:

 
Код:
vector < someclass *> List;

/*- - Обработчик нажатия кнопки - */

someclass * recent = new human;

List.push_back(recent);


Но вот проблема. когда меняем поле List то меняются все поля. Это не хорошо, как этого избежать?
3
26 октября 2006 года
Green
4.8K / / 20.01.2000
Для начала, у тебя хранятся в векторе не объекты класса, а указатели на них. Это разные вещи.

Из того кода, что ты привел, причина твоей ошибки не ясна. Приведи более расширенный код. Где и как ты меняешь list, как понимаешь, что меняются все поля?
1.9K
26 октября 2006 года
burst
94 / / 04.09.2006
Ладно. Не обращайте внимание на предыдущий пост.
вот код:

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "STL.h"
#include  <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

class human{
        public:
        char * name;
        };

        vector <human> list;
        human h0,h1;
        int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

        AnsiString Astr;
        char * Cstr;

        list.push_back(h0);
        list.push_back(h1);

        Astr = Edit1->Text;
        Cstr = Astr.c_str();
        list.name = Cstr;
        i++;

}
//---------------------------------------------------------------------------


Что получается: при первом нажатии на Buttton1 строка из эдита пишется в list[0].name; При втором нажатии на Buttton1 строка из эдита пишется в list[0].name и list[1].name. Почему? там же веть разные объекты h0 и h1



Упс....не в ту ветку запостил. Это Билдер. Извините
3
26 октября 2006 года
Green
4.8K / / 20.01.2000
human::name - это указатель, который указывает как у list[0], так и у list[1] на один объект, получаемый вызовом Astr.c_str().

Т.к. этот объект кроме всего прочего является временным, это двойная ошибка.
1.9K
26 октября 2006 года
burst
94 / / 04.09.2006
а если char * name заменить на char name[] ?
3.0K
26 октября 2006 года
Мerlin
267 / / 25.07.2006
Чтоб прога работала, нужно что-то типа
Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "STL.h"
#include  <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

class human{
        public:
        char * name;
        };

        vector <human> list;
        human h0,h1;
        int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  list.push_back(h0);
  list.push_back(h1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if((i < list.size())&&(Edit1->Text.Length()>0))
  {
    list.name = strdup(Edit1->Text.c_str());
    i++;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  for(int j = 0; j<list.size(); j++)
  {
    delete list[j].name;
  }
}
1.8K
26 октября 2006 года
_const_
229 / / 26.11.2003
Если уж используешь STL, то и замени в human char *name на std::string name. Далее не забудь добавить в human оператор присваивания и конструктор копии (иначе получим побитовую копию!), т.к. контейнеры STL их активно пользуют. Ну а дальше
list.name = Str.c_str();
1.9K
26 октября 2006 года
burst
94 / / 04.09.2006
_const_, спасибо за совет.
А Как сделать так чтобы объект создавался и заносился в вектор по нажатию кнопки ?
1.8K
26 октября 2006 года
_const_
229 / / 26.11.2003
Код:
class human
{
public:
 explicit human(const string& name);
 explicit human(const char *pname); //не забудем проверить на NULL
 human(const human& hum);
 human& operator=(const human& rhs);
 string name;
...
};
...
OnBtnClicked()
{
 list.push_back(human("Vasya Pupkin"));
}
309
26 октября 2006 года
el scorpio
1.1K / / 19.09.2006
C++ Builder - ну тогда всё понятно. Раз задаёте такие вопросы, то запомните как "Отче наш" и повторяйте при каждом запуске Builder'а :"Я никогда не буду использовать char*".
Раз есть TForm - значит используется VCL. Раз есть VCL, значит объявлен класс AnsiString.
Кстати, именно он используется для хранения всех текстовых строк окнонных компонентов, и не существует никаких объективных причин использовать какие-либо другие строковые типы в обработчике интерфейса.
3
26 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=_const_]Далее не забудь добавить в human оператор присваивания и конструктор копии (иначе получим побитовую копию!), т.к. контейнеры STL их активно пользуют.[/QUOTE]
Что за "побитовая копия" ? :)

В данном примере в конструкторе копирования и оператор присваивания определять не нужно. Достаточно и дефолтовых.
1.8K
26 октября 2006 года
_const_
229 / / 26.11.2003
A compiler-generated copy constructor sets up a new object and performs a memberwise copy of the contents of the object to be copied. If base class or member constructors exist, they are called; otherwise, bitwise copying is performed.

В случае с std::string все пройдет отлично, а вот если добавить в human нечто, не имеющее copy-constructor и operator=, то может случиться бяка. Поэтому правило хорошего тона: если нечто используется как элемент STL-контейнера, то лучше объявить copy-constructor и operator=.
3
26 октября 2006 года
Green
4.8K / / 20.01.2000
Откуда этот текст?
Он несколько сбивает с толку. Любой тип имеет конструктор копирования, определенный или дефолтовый. В стандарте нет такого понятия, как bitwise copying.

С тем, что объявлять конструктор копирования и оператор присваивания, так же как и виртуальный деструктор - полезная практика, согласен. Но бывают и исключения.
1.8K
26 октября 2006 года
_const_
229 / / 26.11.2003
MSDN.
Конструктор копирования для встроенных типов - именно bitwise copying.
309
27 октября 2006 года
el scorpio
1.1K / / 19.09.2006
_const_
Вот именно, для встроенных типов. А как только мы в качестве типа реализации шаблона подствим структурированный тип (struct или class), то для него будет использоваться поэлементное копирование.

[quote=Green]С тем, что объявлять конструктор копирования и оператор присваивания, так же как и виртуальный деструктор - полезная практика. [/quote]
Оправдано в трёх целях:
1. Когда при отладке требуется отследить создание/удаление объекта.
2. Когда набор полей и свойств объекта не позволяет однозначно определить порядок присваивания - компилятор явно потребует создать его.
3. Когда одно (несколько) полей класса является указателем на объект, который создаётся и удаляется своим владельцем.

А конструктор "human (const char *Name)" вообще лишний.
 
Код:
// код
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));

Достаточно одного конструктора приведения из типа string.
3
27 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=el scorpio]
Оправдано в трёх целях:
[/QUOTE]
Таких целей можно привести ещё множество, поэтому я бы не стал постулировать конкретное количество целей.

[QUOTE=el scorpio]
А конструктор "human (const char *Name)" вообще лишний.
 
Код:
// код
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));

Достаточно одного конструктора приведения из типа string.
[/QUOTE]
Ты в корне неправ.

human Obj1 = "Указатель на char";
здесь будет вызвано два конструктора: string::string(const char*) и human::human(const char*).

human Obj2 (string ("Указатель на char"));
здесь будет вызваны ТРИ конструктора и один деструктор: string::string(const char*), string::string(const string&), human::human(const string&), string::~string().
Т.о. фрагментируется память, снижается производительность, а про читабельность кода я вообще молчу.
1.8K
27 октября 2006 года
_const_
229 / / 26.11.2003
[QUOTE=el scorpio]
Вот именно, для встроенных типов. А как только мы в качестве типа реализации шаблона подствим структурированный тип (struct или class), то для него будет использоваться поэлементное копирование.
[/QUOTE]
Вообще не понял, к чему это. Элементом же может быть встроенный тип.
1.8K
27 октября 2006 года
_const_
229 / / 26.11.2003
[QUOTE=Green]
human Obj1 = "Указатель на char";
здесь будет вызвано два конструктора: string::string(const char*) и human::human(const char*).
[/QUOTE]
Видимо, имелось в виду human::human(const string&).
Еще string::~string().

[QUOTE=Green]
human Obj2 (string ("Указатель на char"));
здесь будет вызваны ТРИ конструктора и один деструктор: string::string(const char*), string::string(const string&), human::human(const string&), string::~string().[/QUOTE]
Два конструктора. string::string(const string&) лишний.
3
27 октября 2006 года
Green
4.8K / / 20.01.2000
Нет.
Что имелось в виду, то и написано: при конструировании экземпляра в первом случае - два конструктора, во втором три конструктора и один деструктор.
1.8K
27 октября 2006 года
_const_
229 / / 26.11.2003
[QUOTE=Green]Нет.
Что имелось в виду, то и написано: при конструировании экземпляра в первом случае - два конструктора, во втором три конструктора и один деструктор.[/QUOTE]
Так вроде как речь шла об отсутствии human::human(const char*)? (См. сообщение el scorpio)
Третий конструктор - это тот, что будет вызван внутри human::human(const string&)? Тогда да, три.
309
28 октября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=_const_]Вообще не понял, к чему это. Элементом же может быть встроенный тип.[/QUOTE]
Это я к тому, что если для структурированного типа оператор "=" не определён, это не значит, что присваивание выполняется аналогично memcopy. В таком случае будет последовательно вызван оператор "=" для каждогох public свойства
3
28 октября 2006 года
Green
4.8K / / 20.01.2000
А для не public ? :)
398
28 октября 2006 года
Alexandoros
630 / / 21.10.2005
ОФФ:
Почему в темах по с++/стл стока флейма всегда, и так мало в темах, ну допустим, про дрова под виннт ? :)
309
28 октября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Green]А для не public ? :)[/QUOTE]
Я сам сталкивался с ситуацией, когда компилятор требовал переопределённый "operator =" для класса.
Имелся класс "Окружность" с множеством свойств типа read = Get_Property_Value, но без модификатора write.
Компилятор не мог создать шаблонный контейнер для массива этих объектов, пока я не описал процесс присваивания вручную.
3
28 октября 2006 года
Green
4.8K / / 20.01.2000
Дело то не в public, а в том, что требовался специфичный operator= .
А что касается "читаемых свойств типа read", то это вообще никакого отношения к C++ не имеет. Это приблуда Borland-а, причем IMHO вредная.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог