meilleur 3 Réponses c+ - La règle des trois

vote vote

98

class person {     std::string name;     int age;  public:      person(const std::string& name, int age) : name(name), age(age)     {     } };  int main() {     person a("Bjarne Stroustrup", 60);     person b(a);   // What happens here?     b = a;         // And here? } 
// 1. copy constructor person(const person& that) : name(that.name), age(that.age) { }  // 2. copy assignment operator person& operator=(const person& that) {     name = that.name;     age = that.age;     return *this; }  // 3. destructor ~person() { } 
class person {     char* name;     int age;  public:      // the constructor acquires a resource:     // in this case, dynamic memory obtained via new[]     person(const char* the_name, int the_age)     {         name = new char[strlen(the_name) + 1];         strcpy(name, the_name);         age = the_age;     }      // the destructor must release this resource via delete[]     ~person()     {         delete[] name;     } }; 
// 1. copy constructor person(const person& that) {     name = new char[strlen(that.name) + 1];     strcpy(name, that.name);     age = that.age; }  // 2. copy assignment operator person& operator=(const person& that) {     if (this != &that)     {         delete[] name;         // This is a dangerous point in the flow of execution!         // We have temporarily invalidated the class invariants,         // and the next statement might throw an exception,         // leaving the object in an invalid state :(         name = new char[strlen(that.name) + 1];         strcpy(name, that.name);         age = that.age;     }     return *this; } 
// 2. copy assignment operator person& operator=(const person& that) {     char* local_name = new char[strlen(that.name) + 1];     // If the above statement throws,     // the object is still in the same state as before.     // None of the following statements will throw an exception :)     strcpy(local_name, that.name);     delete[] name;     name = local_name;     age = that.age;     return *this; } 
private:      person(const person& that);     person& operator=(const person& that); 
person(const person& that) = delete; person& operator=(const person& that) = delete; 
class person {     std::string name;     int age;  public:     person(const std::string& name, int age);        // Ctor     person(const person &) = default;                // 1/5: Copy Ctor     person(person &&) noexcept = default;            // 4/5: Move Ctor     person& operator=(const person &) = default;     // 2/5: Copy Assignment     person& operator=(person &&) noexcept = default; // 5/5: Move Assignment     ~person() noexcept = default;                    // 3/5: Dtor }; 
vote vote

80

    MyClass x(a, b);     MyClass y(c, d);     x = y; // This is a shallow copy if assignment operator is not provided 
vote vote

72

class Car //A very simple class just to demonstrate what these definitions mean. //It's pseudocode C++/Javaish, I assume strings do not need to be allocated. { private String sPrintColor; private String sModel; private String sMake;  public changePaint(String newColor) {    this.sPrintColor = newColor; }  public Car(String model, String make, String color) //Constructor {    this.sPrintColor = color;    this.sModel = model;    this.sMake = make; }  public ~Car() //Destructor { //Because we did not create any custom types, we aren't adding more code. //Anytime your object goes out of scope / program collects garbage / etc. this guy gets called + all other related destructors. //Since we did not use anything but strings, we have nothing additional to handle. //The assumption is being made that the 3 strings will be handled by string's destructor and that it is being called automatically--if this were not the case you would need to do it here. }  public Car(const Car &other) // Copy Constructor {    this.sPrintColor = other.sPrintColor;    this.sModel = other.sModel;    this.sMake = other.sMake; } public Car &operator =(const Car &other) // Assignment Operator {    if(this != &other)    {       this.sPrintColor = other.sPrintColor;       this.sModel = other.sModel;       this.sMake = other.sMake;    }    return *this; }  } 
Car car1 = new Car("mustang", "ford", "red"); Car car2 = car1; //Call the copy constructor car2.changePaint("green"); //car2 is now green but car1 is still red. 
//Shallow copy example //Assume we're in C++ because it's standard behavior is to shallow copy objects if you do not have a constructor written for an operation. //Now let's assume I do not have any code for the assignment or copy operations like I do above...with those now gone, C++ will use the default.   Car car1 = new Car("ford", "mustang", "red");   Car car2 = car1;   car2.changePaint("green");//car1 is also now green   delete car2;/*I get rid of my car which is also really your car...I told C++ to resolve   the address of where car2 exists and delete the memory...which is also  the memory associated with your car.*/  car1.changePaint("red");/*program will likely crash because this area is  no longer allocated to the program.*/ 

Questions similaires