2016-02-19 4 views
1

В последнее время я часто сбрасываю объект, назначая ему новое значение operator=. Большинство моих классов имеют copy constructor и operator=, определяемые с помощью идиомы «копировать и заменять». В большинстве случаев это прекрасно работает, хотя и не настолько эффективно, как могло бы быть, но в основном это не имеет значения. Есть один случай, когда это не работает. Его, когда destructor нужно вызвать перед constructor нового объекта.Сбросить объект

Примечание: большинство классов, для которых я использую это в uncopyable

class Foo 
{ 
public: 
    Foo() : m_i(0) {} 
    Foo(int i) : m_i(i) {} 

    Foo(Foo&& rhs); 
    Foo& operator=(Foo rhs); 
    friend void swap(Foo& lhs, Foo& rhs); 

private: 
    Foo(Foo& rhs) {} // uncopyable object 

    int m_i; 
}; 

Foo::Foo(Foo&& rhs) 
: Foo() 
{ 
    swap(*this, rhs); 
} 

Foo& Foo::operator=(Foo rhs) 
{ 
    swap(*this, rhs); 
    return *this; 
} 

void swap(Foo& lhs, Foo& rhs) 
{ 
    using std::swap; 
    swap(lhs.m_i, rhs.m_i); 
} 

int main() 
{ 
    Foo f(123); 
    f = Foo(321); // at one time both Foo(123) and Foo(321) exist in memory 
} 

Я тогда учил возможно переписать operator= сначала вручную вызвать destructor, а затем сделать swap (в данном случае rhs будет взято по ссылке const). Однако this answer on stackOverflow заставлял меня думать иначе.

Мне очень нравится оператор = для сброса моих объектов, потому что код чист и такой же, как для встроенных типов (например, int). Он также использует оба кода от constructor и destructor, поэтому дополнительный код не требуется писать и поддерживать.

Итак, мой вопрос: есть ли способ достичь моей цели по сбросу моего объекта с помощью чистого кода и никакого дополнительного кода, который должен быть написан, и чтобы объект был разрушен до того, как будет построен новый?

ответ

1

По определению присвойте новое значение для старого объекта, новое значение было создано до назначения.

Ваш «старый объект» также не разрушен.

Итак, нет. Нет способа. И не должно: вы не должны переопределять «очевидное» поведение оператора присваивания.

Но размещение нового может помочь здесь помимо тильды и экзотического синтаксиса строительства, может быть, этот код подходит «чистый» :)

Foo old(a, b, c); 
old.~Foo(); // explicit destruction 
new (&old) Foo(d, e, f); 
+0

Я мог бы работать с записью метода reset() с использованием синтаксиса нового места размещения. Спасибо за идею. – rozina

1

Если у вас есть код в конструкторе, который также должен быть вызван оператором присваивания, тогда поместите этот код в функцию частного члена и вызовите его как из деструктора, так и из оператора присваивания.

Объект не будет разрушен (и вы не хотите, чтобы это было действительно), но он будет делать то же самое, что и деструктор.

+0

Как видно из примера, нет никакого кода в теле конструктор. Однако переменная 'm_i' инициализируется. Я предполагаю, что переменная может быть установлена ​​в теле конструктора, но это не всегда возможно или желательно. Каков общий подход к сбросу объектов? – rozina