拷贝控制:
拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符,析构函数//拷贝构造函数//class Sales_data {public: Sales_data(const Sales_data &); Sales_data & operator = (const Sales_data &);private: string bookNo; int uints_sold = 0; double revenue = 0.0;};Sales_data::Sales_data(const Sales_data &orig) : bookNo(orig.bookNo), uints_sold(orig.uints_sold), revenue(orig.revenue) {}
如果没有定义拷贝构造函数,编译器会定义一个。即使自己定义了拷贝构造函数,编译器也会合成一个。Sales_data::Sales_data(const Sales_data &orig) : bookNo(orig.bookNo), uints_sold(orig.uints_sold), revenue(orig.revenue) {}拷贝初始化: 直接初始化:string dot(10,'.'); 拷贝初始化:string s2 = dot;//拷贝构造函数发生:将对象作为实参传给非引用的形参//返回一个非引用类型的对象//使用=进行拷贝
1 Sales_data & Sales_data::operator = (const Sales_data &rhs) {2 return *this;3 }//赋值运算符4 extern vector> Permutations(vector &nums);
三五法则//需要析构函数的类也需要拷贝和赋值操作
class HasPtr {public: HasPtr(const string &s = string()) :ps(new std::string(s)), i(0) {}; ~HasPtr() { delete ps; }private: string *ps; int i;};
//使用默认的拷贝构造函数和拷贝赋值运算符,导致多个HasPtr对象指向相同内存
HasPtr f(HasPtr hp) { HasPtr ret = hp; return ret;}
//ret和hp的ps以及传入实参都指向统一内存,析构函数调用时会出现delete两次相同内存,出新错误
需要拷贝操作的类也需要赋值操作
class numbered {public: numbered(const numbered &num) = delete;//删除阻止拷贝 numbered() = default;//显示private: int mysn;};//析构函数不能是删除的成员删除的成员struct PersonInfo { string name; vectorphones;};
1 //行为像值的类 2 class HasPtr { 3 public: 4 HasPtr(const string &s = string()) :ps(new std::string(s)), i(0) {}; 5 HasPtr(const HasPtr &p) : 6 ps(new std::string(*p.ps)), i(p.i) {}; 7 8 ~HasPtr() { delete ps; } 9 private:10 string *ps;11 int i;12 };13 HasPtr& HasPtr::operator = (const HasPtr &rhs) {14 auto newp = new string(*rhs.ps);15 delete ps;//释放旧内存16 ps = newp;17 i = rhs.i;18 /*delete ps;19 ps = new string(*(rhs.ps));20 i = rhs.i;*///自赋值会出现错误,比如rhs和本对象是通过一个对象21 return *this;22 }23 24 //行为像指针的类25 //最好的方法是使用shared_ptr来管理类中的资源,第二种是引用计数26 //除了初始化对象外,每个构造函数要创建一个引用计数27 //拷贝构造函数不分配新的计数器而是拷贝给顶对象的数据成员,包括计数器,拷贝构造函数递增共享的计数器28 //析构函数递减共享的计数器29 //拷贝赋值运算递增右侧运算对象的计数器,递减左侧对象的计数器30 31 32 33 //将计数器保存在动态内存中34 class HasPtr {35 public:36 //构造函数分配新的string和新的计数器,计数器值置137 HasPtr(const string &s = string()) :ps(new std::string(s)), i(0),use(new std::size_t(1)) {};38 HasPtr(const HasPtr &p) :39 ps(p.ps), i(p.i), use(p.use) {40 ++*use;//递增计数41 };//ps保存拷贝对象的内存42 43 ~HasPtr() { }44 private:45 string *ps;46 int i;47 std::size_t *use;48 };49 HasPtr::~HasPtr() {50 if (--*use == 0) {51 delete ps;52 delete use;53 }54 }55 HasPtr& HasPtr::operator = (const HasPtr &rhs) {56 ++*rhs.use;57 if (--*use == 0) {58 delete ps;59 delete use;60 }61 ps = rhs.ps;62 i = rhs.i;63 use = rhs.use; 64 return *this;65 }66 class HasPtr {67 68 friend void swap(HasPtr&, HasPtr&);69 HasPtr(const string &s = string()) :ps(new std::string(s)), i(0) {};70 ~HasPtr() { delete ps; }71 private:72 string *ps;73 int i;74 75 };76 inline void swap(HasPtr &lhs, HasPtr &rhs) {77 using std::swap;78 swap(lhs.ps, rhs.ps);79 swap(lhs.i, rhs.i);80 }