/**
作者: cwl
内容:
带指针类的注意点
c++构造函数,拷贝构造,拷贝赋值
new delete解析
*/
#include <bits/stdc++.h>
using namespace std;
class String {
public:
String(const char* cstr = 0) {
if(cstr) {
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
} else {
m_data = new char[1];
*m_data = ' ';
}
}
///拷贝构造,接受自己这种东西的引用
String(const String& str) {
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
///拷贝赋值,接受自己这种东西的引用
String& operator=(const String &str) {
if(this == &str) {
return *this;
}
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
~String() {
delete[] m_data;
}
char* get_c_str() const {
return m_data;
}
private:
char* m_data;
};
inline ostream&
operator << (ostream& os, const String &str) {
os << str.get_c_str();
return os;
}
int main() {
/**
c++中类四个重要部分
构造函数
析构函数
拷贝构造
拷贝赋值
*/
///[1] 如果你的class如果带着指针,就必须重写拷贝构造和拷贝赋值
/**
构造和析构是带指针的类必备的,而容易被忽略的是下面两个部分。
【1.1】拷贝构造
String(const String& str) {
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
可能会有疑问,str中的m_data明明是private为什么能直接访问?
答:解释有很多,其中一个是一个类的不同对象互为友元
【1.2】拷贝赋值
String& operator=(const String &str) {
if(this == &str) {
return *this;
}
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
杀掉原来的,创建一个同大小的空间,返回。
细节是要检测是否是检测自我赋值。
if(this == &str) {
return *this;
}
多想一步,加强代码稳定性。
下面我们添加输出
inline ostream&
operator << (ostream& os, const String &str) {
os << str.get_c_str();
return os;
}
*/
String a = "hello";
cout << a << endl;
/**
堆和栈
【1】String a("qqq");
a是栈空间,有操作系统创建在作用域{}结束后释放。
自动,auto,也就是旧的时候的auto语义,c++11前的
【2】String *p = new String("asd");
p在栈空间,执行了new处理的堆空间。需要手动delete
否则会出现[内存泄漏]
【3】static int a;
声明周期扩展被扩张
【4】全局对象
生命在main之前,main结束后才析构
*/
///【new】new 会先申请内存,转形,然后调用构造函数
///new 的过程
///注:operator new是一个函数的名字,c++中能查到源代码
/**
String *pc;
void* mem = operator new(sizeof(String)); 申请空间
pc = static_cast<String*>(mem); 类型转化
pc->String::String("asd"); 调用构造函数,直接调会有问题,这里只是示例
*/
///【delete】delete的过程
/// String::~String(ps) //析构函数
/// operator delete(ps) //释放内存
/**
new 和 delete 底层使用malloc和delete获得空间
*/
return 0;
}