В следующем коде, когда используется оператор присваивания, почему не вызывается конструктор копирования или почему нет соответствующего ему отпечатка?
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class Person {
private:
char* name;
int age;
public:
Person() {
name = nullptr;
age = 10;
}
Person(const char* p_name, int p_age) {
name = new char[strlen(p_name) + 1];
strcpy(name, p_name);
age = p_age;
}
Person(Person const& p) {
cout << "Person copy constructor with " << p.name << endl;
name = new char[strlen(p.name) + 1];
strcpy(name, p.name);
age = p.age;
}
/*self assignment
The first is the self-assignment test. This check serves two purposes: it's an easy way to prevent us from running needless code on self-assignment,
and it protects us from subtle bugs (such as deleting the array only to try and copy it).
But in all other cases it merely serves to slow the program down, and act as noise in the code; self-assignment rarely occurs, so most of the time
this check is a waste. It would be better if the operator could work properly without it.*/
/*
Person& operator=(Person const& p) {
cout << "Person copy assignment with " << p.name << endl;
if(this != &p){
delete[] name;
name = nullptr;
name = new char[strlen(p.name) + 1];
strcpy(name, p.name);
age = p.age;
}
return *this;
}
*/
/*exception safety
If in the previous approach the memory allocation fails and throws an exception then the data in name is gone*/
/*
Person& operator=(Person const& p) {
cout << "Person copy assignment with " << p.name << endl;
char* temp_name = new char[strlen(p.name) + 1];
strcpy(temp_name, p.name);
delete[] name;
name = temp_name;
age = p.age;
return *this;
}
*/
//copy and swap idiom
/*
. Not only that, but this choice is critical in C++11, which is discussed later.
(On a general note, a remarkably useful guideline is as follows: if you're going to make a copy of something in a function,
let the compiler do it in the parameter list.‡)
*/
Person& operator=(Person p) {
cout << "Person copy assignment with " << p.name << endl;
swap(*this, p);
return *this;
}
/*
A swap function is a non-throwing function that swaps two objects of a class, member for member. We might be tempted to
use std::swap instead of providing our own, but this would be impossible; std::swap uses the copy-constructor and
copy-assignment operator within its implementation, and we'd ultimately be trying to define the assignment operator in terms of itself!
*/
friend void swap(Person &a, Person &b) {
using std::swap;
swap(a.name, b.name);
swap(a.age, b.age);
}
Person(Person&& other) {
swap(*this, other);
}
~Person() {
if(name)
cout << "Person destructor called for " << name << endl;
delete[] name;
}
};
int main() {
Person p("Ryan", 28);
Person a(p);
a = p;
cout << "Hello World" << endl;
return 0;
}
Вывод приведенного выше кода:
Person copy constructor with Ryan
Person copy constructor with Ryan
Person copy assignment with Ryan
Person destructor called for Ryan
Hello World
Person destructor called for Ryan
Person destructor called for Ryan