2016-06-17 2 views
-1

Я искал некоторые материалы на C++ на this page.Непонятный пример операции присваивания копии

Существует следующий пример относительно оператора присваивания Copy:

Example5& operator= (const Example5& x) { 
    delete ptr;      // delete currently pointed string 
    ptr = new string (x.content()); // allocate space for new string, and copy 
    return *this; 
} 

Это ясно для меня до сих пор, статья однако гласит:

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

Example5& operator= (const Example5& x) { 
    *ptr = x.content(); 
    return *this; 
} 

Я не понимаю, почему это может быть желательно. Не первый пример именно того, чего мы хотим достичь ?: Копия назначение содержимого. Почему «повторно использовать один и тот же строковый объект»?

+0

'x.content()' возвращает копию. Статья была написана без учета семантики движения. –

+1

Повторное использование одного и того же объекта исключает ненужное освобождение и выделение памяти. – GMichael

+6

Удаление объекта и создание нового - ненужные служебные данные, поскольку ptr не const, вы можете изменить его содержимое. Вы все еще копируете. – Kegluneq

ответ

1

В отличие от Java и некоторых других языков, *prt = x.content() скопирует строку из x. Главное преимущество заключается в том, что вам не нужно удалять и переназначать память для строкового объекта, на который указывает ptr (что довольно дорогостоящие операции), но использовать оператор присваивания класса std: string`s class. Кроме того, оператор присваивания строк (для ссылок на lvalue) имеет сильную гарантию исключения, поэтому, если что-то произойдет внутри этого метода, состояние всех объектов будет действительным. И не забывайте, что есть большой шанс (если ptr-> length() < = x.content(). Length()), что не требуется выделение/выделение памяти - копирование только символов.

+2

Класс должен иметь элемент строки в первую очередь, а не указатель на строку. –

+0

@ DanielDaranas для чего? –

+1

Для простоты. В любом случае, он использует семантику копирования. Он в основном хранит (и владеет) строку в объекте. –

6

этой страница говорится:

[...] неявная версия выполняет неполную копию, которая подходит для многих классов, но не для классов с указателями на объекты они обрабатывают его хранения, как случай в примере 5. В этом случае не только класс берет на себя риск удаления заостренного объекта дважды, но назначение создает утечку памяти, не удаляя объект, на который указывает объект перед назначением.

Позволяет увидеть код еще раз:

#include <iostream> 
#include <string> 
using namespace std; 

class Example5 { 
    string* ptr; 
    public: 
    Example5 (const string& str) : ptr(new string(str)) {} 
    ~Example5() {delete ptr;} 
    // copy constructor: 
    Example5 (const Example5& x) : ptr(new string(x.content())) {} 
    // access content: 
    const string& content() const {return *ptr;} 
}; 

Так неявного версии оператора присваивания копии будет эквивалентна

Example5& operator= (const Example5& x) { 
    ptr = x.ptr; // previous value of ptr is lost -> memory leak 
    return *this; 
} 

которые создают утечку памяти, поскольку не освобождают указатель элемента на this.ptr. Предлагаемая версия deallocate ptr затем выделяет для нее новую память. Deallocating и распределения нести дополнительные расходы и дополнительные инструкции, поэтому второй код

Example5& operator= (const Example5& x) { 
    *ptr = x.content(); 
    return *this; 
} 

повторное же (уже выделено) области памяти (this-> PTR) для хранения копии *x.ptr.

Обратите внимание, что поскольку x.content() возвращает копию строки в x, *ptr = x.content(); будет вызывать copy assignment operator из *ptr, который в тиа случае является строкой.

+0

ОК, но из того, что я получаю, это приемлемо только тогда, когда 'string * ptr;' определенно создается/выделяется при построении примера5? Наверное, я мысленно застрял, потому что '* ptr = x.content();' выглядит как своего рода рискованное задание, предполагая, что 'ptr'already существует. –

+0

Это выглядит рискованно, но на самом деле 'x.content()' возвращает копию '* x.ptr' и вызывает оператор * копирования * для строки. В примере применяется строка, которая будет назначаться всякий раз, когда конструктор называется так, да, он работает в этих условиях. –

Смежные вопросы