// Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;
//自定义字符串包装类
class MyString
{
public:
MyString();
MyString(char * value);
MyString(const MyString &str); //拷贝构造
~MyString();
//重载赋值运算符 将数组中的每个元素都进行复制
const MyString& operator = (const MyString &str);
friend ostream & operator << (ostream & out, const MyString& str);
private:
int m_length; //字符串实际长度 不包括\0
char *m_value; //实际存储字符的字符数组
};
MyString::MyString():m_length(0)
{
//char *str = ""; //长度为0 ,但是实际的字符数组中会存在唯一的元素 ‘\0’;
this->m_value = new char[m_length + 1]; //长度为1的时候存放 ‘\0’
this->m_value[0] = '\0';
}
MyString::MyString(char * value)
{
//将传入的字符串的值赋给当前对象中的m_value
if (nullptr == value)
{
this->m_value = new char[m_length + 1]; //长度为1的时候存放 ‘\0’
this->m_value[0] = '\0';
}
m_length = strlen(value); //求出实际赋值的字符串长度
m_value = new char[m_length + 1]; //为\0留
strcpy_s(m_value, m_length + 1,value);
}
MyString::MyString(const MyString &str)
{
delete[]m_value; //释放原有内存资源
m_length = strlen(str.m_value);
m_value = new char[m_length + 1];
strcpy_s(m_value, m_length + 1, str.m_value);
}
MyString::~MyString()
{
delete[] m_value; //释放字符数组所指向的空间
}
//当重载赋值运算符时,务必确定将一个对象中的所有数据都赋值到另一个对象中(特别是有指针时)(深拷贝)
const MyString& MyString::operator = (const MyString &str)
{
if (this == &str) return *this;
delete[] m_value; //首先要释放字符串的原始空间
m_length = str.m_length;
m_value = new char[m_length + 1];
strcpy_s(m_value, m_length + 1, str.m_value);
return *this; //返回当前对象的引用
}
ostream & operator << (ostream & out, const MyString& str)
{
out << str.m_value << "\n";
out << "m_value的长度为:" << strlen(str.m_value);
return out;
}
void main()
{
MyString str1("abc") ; //普通的构造函数
MyString str = str1; //需要重载赋值运算符
MyString str(str1); //需要调用拷贝构造函数
cout << str << endl;
system("pause");
}
在下面三种场景中会调用拷贝构造函数
- 当类的对象被初始化为同一类的另一个对象时
- 当对象被作为参数传递给一个函数时
- 当函数返回一个对象时
具体文本解释可参照: