Проблема такая. Переписываю старую прогу с старого билдера 5 на MS VS2005
Там был такой класс, как Array. Судя с использования — массив указателей + плюс разные примочки(добавить/убрать элемент).
Так как VC++ я не нашёл подобного класса, решил использовать вектор с stl.
В общем имеем такой код
class Foo
{
}
class Bar
{
private:
vector<Foo> foo;
}
Bar *bar = new Bar();
Вопрос. Нужно ли в конструкторе/деструкторе класса Bar какие то дополнительные манипуляции с классом Foo? На данный момент даже скомпилировать не могу свой код — там ещё на недельку-другую переделывать.
class Foo
{
}
class Bar
{
private:
vector<Foo> foo;
}
Bar *bar = new Bar();
OV>Вопрос. Нужно ли в конструкторе/деструкторе класса Bar какие то дополнительные манипуляции с классом Foo? На данный момент даже скомпилировать не могу свой код — там ещё на недельку-другую переделывать.
Зависит от того, что вы хотите
По тому, что у вас написано — будет создан пустой вектор с количеством элементов равным 0.
При уничтожении объекта Bar пямять занимаемая вектором будет особождена автоматически(разумеется если у вас там храняться указатели — память на которую они ссылаются будет потеряна).
Здравствуйте, OdesitVadim, Вы писали:
OV>Проблема такая. Переписываю старую прогу с старого билдера 5 на MS VS2005 OV>Там был такой класс, как Array. Судя с использования — массив указателей + плюс разные примочки(добавить/убрать элемент). OV>Так как VC++ я не нашёл подобного класса, решил использовать вектор с stl. OV>В общем имеем такой код OV>
OV>class Foo
OV>{
OV>}
OV>class Bar
OV>{
OV>private:
OV> vector<Foo> foo;
OV>}
OV>Bar *bar = new Bar();
OV>
OV>Вопрос. Нужно ли в конструкторе/деструкторе класса Bar какие то дополнительные манипуляции с классом Foo? На данный момент даже скомпилировать не могу свой код — там ещё на недельку-другую переделывать.
Если вектор храннит именно объекты типа Foo, то никаких дополнительных действий не нужно.
Но похоже, что для сохранения функционала тебе нужен вектор указателей vector<Foo*> (
Там был такой класс, как Array. Судя с использования — массив указателей
), и тогда за временем жизни объектов придется следить самостоятельно. Ну или воспользоваться умными указателями.
Здравствуйте, OdesitVadim, Вы писали:
OV>Проблема такая. Переписываю старую прогу с старого билдера 5 на MS VS2005 OV>Там был такой класс, как Array. Судя с использования — массив указателей + плюс разные примочки(добавить/убрать элемент). OV>Так как VC++ я не нашёл подобного класса, решил использовать вектор с stl. OV>В общем имеем такой код OV>
OV>class Foo
OV>{
OV>}
OV>class Bar
OV>{
OV>private:
OV> vector<Foo> foo;
OV>}
OV>Bar *bar = new Bar();
OV>
OV>Вопрос. Нужно ли в конструкторе/деструкторе класса Bar какие то дополнительные манипуляции с классом Foo? На данный момент даже скомпилировать не могу свой код — там ещё на недельку-другую переделывать.
std::vector хранит элементы по значению.
Если тебе нужен массив именно указателей — можно использовать либо std::vector< boost::shared_ptr<Foo> >, либо std::vector< Foo* >, но в последнем случае придется удалять элементы вручную в деструкторе Bar.
B>Если вектор храннит именно объекты типа Foo, то никаких дополнительных действий не нужно.
Тогда меня устраивает B>Но похоже, что для сохранения функционала тебе нужен вектор указателей vector<Foo*> ( B>
B>Там был такой класс, как Array. Судя с использования — массив указателей
B>), и тогда за временем жизни объектов придется следить самостоятельно. Ну или воспользоваться умными указателями.
поле приватно и для доступа к элементам используется такой код
Foo& getfoo(int index);
Вот я и думаю, как корректней вызовы переделать
мне кажеться где то так
return &foos.at(i);
хотя по поводу & не уверен
Здравствуйте, dip_2000, Вы писали:
_>Зависит от того, что вы хотите _>По тому, что у вас написано — будет создан пустой вектор с количеством элементов равным 0.
Это меня устроит. Я потом сам туда элементов напхаю. _>При уничтожении объекта Bar пямять занимаемая вектором будет особождена автоматически(разумеется если у вас там храняться указатели — память на которую они ссылаются будет потеряна).
Если деструкторы Foo будут вызваны, то он за собой подчистит всё как надо
Здравствуйте, OdesitVadim, Вы писали:
OV>поле приватно и для доступа к элементам используется такой код OV>
OV>Foo& getfoo(int index);
OV>
OV>Вот я и думаю, как корректней вызовы переделать OV>мне кажеться где то так OV>return &foos.at(i); OV>хотя по поводу & не уверен
Можно так:
return foos.at(i);
или так:
return foos[i];
В первом случае будет производится проверка на допустимость индекса, и если что-то не так, то at бросит исключение out_of_range.
Во втором случае никаких проверок не производится.
Здравствуйте, OdesitVadim, Вы писали:
OV>хотя по поводу & не уверен
А нужно ли, чтобы адрес элемента этого вектора в течении его жизни не менялся?
Если это не нужно (грубо говоря для доступа всегда используется этот метод и указатель нигде не кэшируется), то всё и так получится, а если нужно, то не получится, так как вектор не гарантирует сохранение указателей на свои элементы.
Тогда надо будет таки хоранить указатели на объекты, и как-то управлять времени их жизни.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, OdesitVadim, Вы писали:
OV>Здравствуйте, dip_2000, Вы писали:
_>>Зависит от того, что вы хотите _>>По тому, что у вас написано — будет создан пустой вектор с количеством элементов равным 0. OV>Это меня устроит. Я потом сам туда элементов напхаю. _>>При уничтожении объекта Bar пямять занимаемая вектором будет особождена автоматически(разумеется если у вас там храняться указатели — память на которую они ссылаются будет потеряна). OV>Если деструкторы Foo будут вызваны, то он за собой подчистит всё как надо
Я так понял Foo чем-то владеет. У него определены копирующий конструктор и оператор=()? Нужно учесть, что при хранении по значению, Foo должен уметь корректно копироваться. Так как по мере роста вектор выделяет новуя память, копирует старые элементы на нове место, а затем старые элементы удаляет.
Ещё нужно помнить, что при хранении по значению невозможно использовать полиморфизм. У вас этот Array содержал разностипные элементы?
Здравствуйте, SuhanovSergey, Вы писали: SS>Я так понял Foo чем-то владеет. У него определены копирующий конструктор и оператор=()? Нужно учесть, что при хранении по значению, Foo должен уметь корректно копироваться.
Ну это не сложно написать. SS>Так как по мере роста вектор выделяет новуя память, копирует старые элементы на нове место, а затем старые элементы удаляет.
Вектор при один раз при старте программы заполняется данными и дальше с него только читают/модифицируют поля вложенного класса. SS>Ещё нужно помнить, что при хранении по значению невозможно использовать полиморфизм. У вас этот Array содержал разностипные элементы?
Нет. Исключительно однотипные элементы.
Здравствуйте, Bell, Вы писали:
B>В первом случае будет производится проверка на допустимость индекса, и если что-то не так, то at бросит исключение out_of_range. B>Во втором случае никаких проверок не производится.
Вот об этом я и подумал, и решил, что на первое время исключения нада.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, OdesitVadim, Вы писали:
E>А нужно ли, чтобы адрес элемента этого вектора в течении его жизни не менялся? E>Если это не нужно (грубо говоря для доступа всегда используется этот метод и указатель нигде не кэшируется), то всё и так получится, а если нужно, то не получится, так как вектор не гарантирует сохранение указателей на свои элементы.
E>Тогда надо будет таки хоранить указатели на объекты, и как-то управлять времени их жизни.
Там всё мирно. Взяли объект, поменяли одно-два поля и забыли. Никто нигде не кеширует.
тоесть почти кругов вызов происходит где то так
bar.getfoos(i).somemetod();
Здравствуйте, OdesitVadim, Вы писали:
B>>В первом случае будет производится проверка на допустимость индекса, и если что-то не так, то at бросит исключение out_of_range. B>>Во втором случае никаких проверок не производится. OV>Вот об этом я и подумал, и решил, что на первое время исключения нада.
Мне кажется, это некорректный подход. Это же не ассерты, которые только в дебаге проявляются. Это выбор решения. Либо ты используешь исключения, либо сам проверяешь границы массива.
Здравствуйте, i-maverick, Вы писали:
IM>Здравствуйте, OdesitVadim, Вы писали:
B>>>В первом случае будет производится проверка на допустимость индекса, и если что-то не так, то at бросит исключение out_of_range. B>>>Во втором случае никаких проверок не производится. OV>>Вот об этом я и подумал, и решил, что на первое время исключения нада.
IM>Мне кажется, это некорректный подход. Это же не ассерты, которые только в дебаге проявляются. Это выбор решения. Либо ты используешь исключения, либо сам проверяешь границы массива.
Ну так на данный момент, так как код не мой и я не знаю, есть ли в нём потенциальные баги я делаю с at. На дальше, если проблем не будет, переправлю. Благое дело, благодаря структуре классов, это нужно делать в двух местах и всё (для двух разных классов). Хотя наверное может и оставлю at. Там за производительностью некуда гнаться.
В общем я ещё не определился
Здравствуйте, OdesitVadim, Вы писали:
OV>Там всё мирно. Взяли объект, поменяли одно-два поля и забыли. Никто нигде не кеширует. OV>тоесть почти кругов вызов происходит где то так OV>bar.getfoos(i).somemetod();
Ну тогда наверное можно и как у тебя
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, OdesitVadim, Вы писали:
OV>>Там всё мирно. Взяли объект, поменяли одно-два поля и забыли. Никто нигде не кеширует. OV>>тоесть почти кругов вызов происходит где то так OV>>bar.getfoos(i).somemetod();
E>Ну тогда наверное можно и как у тебя
Тоесть, вектор гарантирует, что если я получил по ссылке обект с вектора и в нескольких строках ниже модифицирую этот объект (поля его), но не трогаю вектор, то плохого ничего не будет (вектор сам не перераспределит объекты в памяти и ссылка перестанет быть валидной)
Если в стандарте указания, после какие методы вектора безопасны, а какие нет по отношению к валидности ссылки?
Здравствуйте, OdesitVadim, Вы писали:
OV>Если в стандарте указания, после какие методы вектора безопасны, а какие нет по отношению к валидности ссылки?
модифицирующие
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, OdesitVadim, Вы писали:
OV>>Если в стандарте указания, после какие методы вектора безопасны, а какие нет по отношению к валидности ссылки? E>модифицирующие
Мда, ответ программиста. Ну это понятно, модифицирующие. Как говорил докдор: "Имя, сестра, имя!"
Здравствуйте, OdesitVadim, Вы писали:
OV>Здравствуйте, Erop, Вы писали:
E>>Здравствуйте, OdesitVadim, Вы писали:
OV>>>Там всё мирно. Взяли объект, поменяли одно-два поля и забыли. Никто нигде не кеширует. OV>>>тоесть почти кругов вызов происходит где то так OV>>>bar.getfoos(i).somemetod();
E>>Ну тогда наверное можно и как у тебя OV>Тоесть, вектор гарантирует, что если я получил по ссылке обект с вектора и в нескольких строках ниже модифицирую этот объект (поля его), но не трогаю вектор, то плохого ничего не будет (вектор сам не перераспределит объекты в памяти и ссылка перестанет быть валидной)
Да, ничего плохого не случится.
OV>Если в стандарте указания, после какие методы вектора безопасны, а какие нет по отношению к валидности ссылки?
Конечно есть. Все модифицирующие методы вектора потенциально ведут к инвалидации ссылок/итераторов. Подробнее смотри 23.2.4.
Здравствуйте, OdesitVadim, Вы писали:
OV>Проблема такая. Переписываю старую прогу с старого билдера 5 на MS VS2005 OV>Там был такой класс, как Array. Судя с использования — массив указателей + плюс разные примочки(добавить/убрать элемент). OV>Так как VC++ я не нашёл подобного класса, решил использовать вектор с stl. OV>В общем имеем такой код OV>
OV>class Foo
OV>{
OV>}
OV>class Bar
OV>{
OV>private:
OV> vector<Foo> foo;
OV>}
OV>Bar *bar = new Bar();
OV>
OV>Вопрос. Нужно ли в конструкторе/деструкторе класса Bar какие то дополнительные манипуляции с классом Foo? На данный момент даже скомпилировать не могу свой код — там ещё на недельку-другую переделывать.
Ничего не нужно. Всё сделается автоматически. Только, если вы будете использовать указатели vector<Foo*>, то не забывайте удалять каждый элемент в векторе.
Плюс, после закрывающейся скобки при определении класса надо ставить точку с запятой.