Подскажите: насколько безопасно делать вот такую штуку?
CSample::CSample(const CSample& smpl)
{
*this = smpl;
}
Здравствуйте, Аноним, Вы писали:
А> Подскажите: насколько безопасно делать вот такую штуку?
А> CSample::CSample(const CSample& smpl)
А> {
А> *this = smpl;
А> }
Такая штука всего-навсего вызовет копирующий оператор присваивания. От него безопасность и зависит.
Здравствуйте, Аноним, Вы писали:
А> Подскажите: насколько безопасно делать вот такую штуку?
А>А> CSample::CSample(const CSample& smpl)
А> {
А> *this = smpl;
А> }
А>
Не безопаснее, чем вызов функции — члена.
Здравствуйте, Аноним, Вы писали:
А> Подскажите: насколько безопасно делать вот такую штуку?
А>А> CSample::CSample(const CSample& smpl)
А> {
А> *this = smpl;
А> }
А>
А если попробовать так
CSample::CSample(const CSample& smpl)
{
this = &smpl;
}
Здравствуйте, Vamp, Вы писали:
S_>>А если попробовать так
S_>>CSample::CSample(const CSample& smpl)
S_>>{
S_>> this = &smpl;
S_>>}
V>Попробуй...
)
Понял, на одну обл памяти будут ссылаться два указателя...
Ну и что! Кто же не ошибается!
Здравствуйте, Аноним, Вы писали:
А> Подскажите: насколько безопасно делать вот такую штуку?
А>А> CSample::CSample(const CSample& smpl)
А> {
А> *this = smpl;
А> }
А>
Так! Герба Саттера хотят обойти!
А это базовый класс или потомок?
Не произойдет ли здесь срезка?
Здравствуйте, Аноним, Вы писали:
А>А> CSample::CSample(const CSample& smpl)
А> {
А> *this = smpl;
А> }
А>
ТАК — совсем небезопасно.
Вот представь себе, что твой CSample такой:
class CSample {
CAnotherSample *pData_;
public:
CSample::CSample(const CSample& smpl)
{
*this = smpl;
}
CSample& operator=(const CSample& smpl)
{
delete pData_;
if( 0 != smpl.pData_ )
pData_ = smpl.pData_->make_copy_of();
else
pData_ = 0;
}
}
Ну, и что мы теперь имеем ?
При вызове оператора присваивания из конструктора pData_ содержит мусор.
Мы же попытаемся вызвать на него деструктор. В процессе получаем доской по морде.
Мораль:
Если хочется инициализироваться через оператор присваивания, не забудь перед этим установить
все данные класса в какое-то осмысленное значение. То есть примерно так:
CSample::CSample(const CSample& smpl)
:pData_(0)
,pAntoherData_(0)
,pYetAntoherData_(0)
{
*this = smpl;
}
Лично мне такая инициализация категорически не нравится. Смотри почему:
— Задача конструктора — просто создать обьект на "пустом месте" — очистки состояния не требуется, так как никакого состояния собственно и нет.
— Задача оператора присваивания — откуда-то скопировать состояние обьекта.
Естественно, перед копированием чужого состояния он должен удалить свое собственное.
То есть, оператор присваивания должен выполнять работу:
(а) деструктора — т.е. удалить состояние.
(б) конструктора копирования — на пустое место скопировать чужое состояние.
И при этом еще в случае возникновеения исключения надо оставить обьект в консистентном состоянии...
Короче, я тебе не завидую.
Поэтому, гораздо лучше делать наоборот — реализовывать оператор присваивания через конструктор копирования и метод swap(). Если swap() не будет бросаться исключениями (а в большинстве случаев это вполне достижимо), то все будет очень и очень кузяво.
Примерно так:
CSample& CSample::operator=(const CSample& rhs)
{
CSample tmp(rhs); //создаем временную копию обьекта...
this->swap(rhs); //обмениваемся состояниями между this и копией...
return *this; //теперь this содержит состояние копии
// а копия (в которой теперь лежит то что было в this) будет уничтожена по выходу из метода...
}
void CSample::swap(CSample& rhs)
{
std::swap( this->pData_, rhs.pData_);
std::swap( this->pAntoherData_, rhs.pAntoherData_ );
std::swap( this->pYetAntoherData_, rhs.pYetAntoherData_ );
}
Здравствуйте, TepMuHyc, Вы писали:
TMH>Поэтому, гораздо лучше делать наоборот — реализовывать оператор присваивания через конструктор копирования и метод swap(). Если swap() не будет бросаться исключениями (а в большинстве случаев это вполне достижимо), то все будет очень и очень кузяво.
TMH>Примерно так:
TMH>TMH>CSample& CSample::operator=(const CSample& rhs)
TMH>{
TMH> CSample tmp(rhs); //создаем временную копию обьекта...
this->>swap(rhs); //обмениваемся состояниями между this и копией...
TMH> return *this; //теперь this содержит состояние копии
TMH> // а копия (в которой теперь лежит то что было в this) будет уничтожена по выходу из метода...
TMH>}
TMH>void CSample::swap(CSample& rhs)
TMH>{
TMH> std::swap( this->pData_, rhs.pData_);
TMH> std::swap( this->pAntoherData_, rhs.pAntoherData_ );
TMH> std::swap( this->pYetAntoherData_, rhs.pYetAntoherData_ );
TMH>}
TMH>
Именно то, что советует Герб Саттер в своей книжке!!!
Здравствуйте, LaptevVV, Вы писали:
L> А это базовый класс или потомок?
L> Не произойдет ли здесь срезка?
А при чем здесь это? Или оператор присваивания полиморфен?
-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.8 beta