拷贝构造器

由己存在的对象,创建新对象。也就是说新对象,不由构造器来构造,而是由拷贝构造器来完成。拷贝构造器的格式是固定的。

class 类名
{
类名(const 类名 & another)
拷贝构造体
}
class A
{
A(const A & another)
{}
}

规则:

1 系统提供默认的拷贝构造器。一经实现,不复存在。

2 系统提供的时等位拷贝,也就是所谓的浅浅的拷贝。

3 要实现深拷贝,必须要自定义。

4 浅拷贝,会导致内存重析构。linux下浅拷贝会挂机。double free,在有些情况下(含有堆空间的时候),要实现自拷贝构造

#include <iostream>
#include "mystring.h" using namespace std; int main()
{
string s = "assassin";
string ss(s);
cout<<"++++++++++++++++"<<endl;
cout<<ss<<endl;
cout<<"++++++++++++++++"<<endl; mystring s1 = "intelwisd";
mystring ss1(s1);//浅复制,两个对象指向同一个地址空间,释放对象的时候释放了两次对象所指向的地址空间。
cout<<"++++++++++++++++"<<endl;
cout<<ss1.c_str()<<endl;
cout<<"++++++++++++++++"<<endl; string sss = s; mystring sss1 = s1;//也可以实现,本质也是拷贝,用已有一个对象完成一个对象,从无到有的创建过程。 string ssss;
ssss = s; mystring ssss1;
ssss1 = s1;//默认的也可以,本质是赋值运算符重载---> this指针。 return 0;
}
#ifndef MYSTRING_H
#define MYSTRING_H class mystring
{
public:
//mystring();
mystring(const char *s = NULL);//无参的形式包含在里面
char * c_str();
mystring(const mystring & another);
~mystring();
private:
char * _str;
}; #endif // MYSTRING_H
#include<iostream>
#include "mystring.h"
#include "string.h"
using namespace std; mystring::mystring(const char *s)
{
if(s == NULL)
{
_str = new char[1];
*_str = '\0';
}else{
int len = strlen(s);
_str = new char[len+1];
strcpy(_str,s);
} } char * mystring::c_str()
{
return _str;
}
mystring::mystring(const mystring & another)
{
//_str = another._str;//同类之间没有隐私,这样的浅复制会造成内存重析构。
int len = strlen(another._str);
_str = new char[len+1];
strcpy(_str,another._str);
} mystring::~mystring()
{
delete []_str;
}

this 指针

系统在创建对象时,默认生成的指向当前对象的指针。这样作的目的,就是为了带来方便。

作用

1,避免构造器的入参与成员名相同。

2,基于 this 指针的自身引用还被广泛地应用于那些支持多重串联调用的函数中。

class Stu
{
public:
Stu(string name,int age)
{
this->name = name;
this->age = age;
}
void display()
{
cout<<name<<"+++"<<age<<endl;
}
Stu & growUp()
{
this->age++;
return *this;
}
private:
string name;
int age;
}
int main()
{
Stu s("assassin",23);
dout<<"&s:"<<&s<<endl;
s.display();
s.growUp().growUp().growUp().growUp().display();//年龄增加 return 0;
}

赋值运算符重载(Operator=)

用一个己有对象,给另外一个己有对象赋值。两个对象均己创建结束后,发生的赋值行为。

格式:

类名
{
类名& operator=(const 类名& 源对象)
拷贝体
}
class A
{
A& operator=(const A& another)
{
//函数体
return *this;
}
};

规则:

1 系统提供默认的赋值运算符重载,一经实现,不复存在。

2 系统提供的也是等位拷贝,也就浅拷贝,会造成内存泄漏,重析构。

3 要实现深深的赋值,必须自定义。

4 自定义面临的问题有三个:

1,自赋值

2,内存泄漏

3,重析构。

5 返回引用,且不能用 const 修饰。a = b = c => (a+b) = c

mystring & mystring::operator=(const mystring & another)
{
if(this == &another)//复制自己的情况
return *this;
delete []this->_str;//先把自己的释放掉
int len = strlen(another._str);
this->_str = new char [len+1];
strcpy(this->_str,another._str); return *this;
}

完整代码:

#include<iostream>
#include "mystring.h"
#include "string.h"
using namespace std; mystring::mystring(const char *s)
{
if(s == NULL)
{
_str = new char[1];
*_str = '\0';
}else{
int len = strlen(s);
_str = new char[len+1];
strcpy(_str,s);
} } char * mystring::c_str()
{
return _str;
}
mystring::mystring(const mystring & another)
{
//_str = another._str;//同类之间没有隐私,这样的浅复制会造成内存重析构。
int len = strlen(another._str);
_str = new char[len+1];
strcpy(_str,another._str);
} mystring::~mystring()
{
delete []_str;
}
mystring& mystring:: operator=(const mystring & another)
{
if(this == &another)//复制自己的情况
return *this;
delete []this->_str;//先把自己的释放掉
int len = strlen(another._str);
this->_str = new char [len+1];
strcpy(this->_str,another._str); return *this;
}
#ifndef MYSTRING_H
#define MYSTRING_H class mystring
{
public:
//mystring();
mystring(const char *s = NULL);//无参的形式包含在里面
char * c_str();
mystring(const mystring & another);
mystring& operator=(const mystring & another);
~mystring();
private:
char * _str;
}; #endif // MYSTRING_H
#include <iostream>
#include "mystring.h" using namespace std; int main()
{
string s = "assassin";
string ss(s);
cout<<"++++++++++++++++"<<endl;
cout<<ss<<endl;
cout<<"++++++++++++++++"<<endl; mystring s1 = "intelwisd";
mystring ss1(s1);//浅复制,两个对象指向同一个地址空间,释放对象的时候释放了两次对象所指向的地址空间。
cout<<"++++++++++++++++"<<endl;
cout<<ss1.c_str()<<endl;
cout<<"++++++++++++++++"<<endl;
string sss;
sss = s; mystring sss1;//
sss1 = s1; return 0;
}

最新文章

  1. 手写一个json格式化 api
  2. SQL事务用法begin tran,commit tran和rollback tran的用法
  3. Pattern和Matcher
  4. windows 2012 服务器打开ping端口,开通远程连接
  5. iOS开发——GCD多线程详解
  6. AJAX实例入门
  7. 【Beta】 第七次Daily Scrum Meeting
  8. js的观察者模式
  9. javascript 操作节点的属性
  10. 从零开始学spring cloud(十) -------- hystrix简单代码示例
  11. CentOS7 安装MySQL5.6
  12. Leetcode 686 Repeated String Match
  13. AviSynth AVS Importer Plugin for Adobe Premiere Pro CC 2015 x64
  14. VBA找相似体积的单元格值
  15. python中的函数对象的内存地址是多少
  16. Mybatis的in使用
  17. Linux:Apache安装与启动
  18. redis 学习资料
  19. JS数字格式化(用逗号隔开 代码已做了修改 支持0-9位逗号隔开)
  20. SQL2008数据库导出到SQL2000全部步骤过程

热门文章

  1. ios开发经常使用到的第三方库
  2. linux下创建带password的用户
  3. Introduction to MongoDB
  4. 84.Node.js -Mongoose 方法
  5. C#篇(三)——函数传参之引用类型和值类型
  6. Oracle 常用内置函数
  7. Android 代码中使用Color工具类 parseColor
  8. js数组的操作 Full
  9. linq replace with single call to FirstOrDefault 解决使用resharper产生的警告
  10. Perceptron Learning Algorithm(python实现)