2016-07-15 3 views
-2

Я хотел бы знать, допустимо ли копирование объекта следующим образом при копировании отдельных элементов.Копирование объекта в C++

#include <iostream> 
using namespace std; 

class abc{ 
public: 
    abc(int a = 10, int b = 5); 
    abc(const abc &obj, int b = 10); 

    int ret_x() { return x; } 
    int ret_y() { return y; } 
private: 
    int x; 
    int y; 
}; 

abc::abc(int a, int b) 
    : x(a), 
    y(b) 
{ 
} 

abc::abc(const abc &obj, int b) 
{ 
    if (this != &obj) { 
     *this = obj; -----> Copying the object 
    } 
    y = b; 
} 

int main() 
{ 
    abc a1; 
    cout << "A1 values: " << a1.ret_x() << "\t" << a1.ret_y() << endl; 
    abc a2(a1, 20); 
    cout << "A2 values: " << a2.ret_x() << "\t" << a2.ret_y() << endl; 

    return 0; 
} 

Edit:

использования:

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

Код работает нормально, но является ли метод правильным?

Спасибо!

+0

Вы строительство нового объекта - если бы это имеет смысл для нового объекта, чтобы создать из себя? – chris

+0

Я так не вижу конструктора. Копировать конструктор является копией из других. Но вы включаете свой специальный intialize одной переменной-члена, этот код нарушает здравый смысл конструктора копирования. Почему начальный конструктор b 5, но исходный конструктор исходного кода b 0? –

+0

@TongxuanLiu: Добавленный случай использования – Maddy

ответ

2

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

abc a; 
abc* b = new(&a)abc(a); 

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

В вашем специальном случае это кажется ОК, поскольку данных нет, что может потребовать глубокого копирования. Однако имейте в виду, что вы назначаете член b дважды. Не очень важно с int, но на более крупных объектах (std :: string, std :: vector, ...), которые делают глубокие копии, становится все более и более сомнительным.

С C++ 11, хотя я предпочел бы конструктор делегацию:

abc::abc(const abc& obj, int b) 
    : abc(obj) // copying here 
{ 
    y = b; 
} 

Это не решает, однако, проблема двойного назначения. Честно говоря, это не всегда может быть настоящей проблемой, во многих случаях компилятор может оптимизировать первое присваивание (особенно в случае int нашего примера). Но по более сложным типам данных (возможно, уже std :: string) я не чувствовал бы себя комфортно, полагаясь на компилятор, обнаруживающий устаревшее назначение ...

Помните, что у вас могут возникнуть проблемы, если у вас есть ресурсы, управляемые внутренне:

struct abc 
{ 
    int* array; 
    abc() : array(new int[7]) { } 
    ~abc() 
    { 
     delete[] array; 
    } 
} 

Не обеспечивая соответствующий оператор присваивания или конструктор копирования – в зависимости от варианта реализации, ваш (назначение) или мои (конструктор делегирование) – делает необходимую глубокую копию приведет к множественному удалению одних и те же данные (не определено поведение!). Следуя rule of three (или совсем недавно, rule of five), вам, скорее всего, понадобятся оба варианта. Тогда вы можете подумать об идиоме copy and swap idiom.

Наконец трюк, чтобы избежать двойного назначения:

abc(abc const& other) 
    : abc(other, other.y) 
{ } 

abc(abc const& other, int y) 
    : x(other.x), y(y) 
{ } 
+0

Рад, что вы упомянули о [ Правило трех] (https://en.wikipedia.org/wiki/Rule_of_three_ (C% 2B% 2B_programming)), отвечая на него. – user1336087

+0

@Aconcagua: Добавлен прецедент для этого. – Maddy

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