赞
踩
#include "String.h" int main(void) { //深拷贝与浅拷贝 String s1("AAA"); s1.Display(); String s2 = s1; //若自己没有实现一个拷贝构造函数, 则调用系统提供的默认的拷贝构造函数 // 系统提供的默认拷贝构造函数实施的是浅拷贝,等价于s2.str_ = s1.str_, //如果还有其他成员,就是逐成员赋值 //这里s2中的str_指针与s1中的str_指针指向同一块内存,在构造s2对象的时候没有分配自己的内存, //两个对象指向同一块内存 //当2个对象生存周期结束时,都要调用析构函数,同一块内存被释放2次,因而出现了运行时错误 //解决办法:不使用系统提供的默认的拷贝构造函数,自己实现一个拷贝构造函数 //赋值运算 String s3; s3.Display(); s3 = s2; // 调用等号运算符 // 系统提供的默认等号运算符实施的是浅拷贝,等价于s3.str_ = s2.str_;如果还有其他成员,就是逐成员赋值,也会出现一个对象被销毁2次, //所以提供自己的等号运算符 // s3.operator=(s2); //禁止拷贝 // 要让对象是独一无二的,我们要禁止拷贝 // 方法是将拷贝构造函数与=运算符声明为私有,并且不提供它们的实现 return 0; }
#ifndef _STRING_H_ #define _STRING_H_ class String { public: String(char* str="");//默认参数是空串 ~String(); String(const String& other); String& operator=(const String& other); void Display(); private: char* AllocAndCpy(char* str); char* str_;//类内部涉及到动态内存分配,则使用深拷贝,除了共享内存 //禁止拷贝的做法:若是独一无二的对象,独一无二的对象不允许拷贝,将声明以及实现都注释掉,所以会导致编译出错 // String(const String& other); // String& operator=(const String& other); }; #endif // _STRING_H_
15cpp\15cpp\15cpp\String.cpp
#include "String.h" #include <cstring>//等价于#include <string.h> #include <iostream> using namespace std; String::String(char* str/* = */) { str_ = AllocAndCpy(str); } String::~String() { delete[] str_; } //错误的浅拷贝做法:自己实现一个拷贝构造函数 String::String(const String& other) : str_(other.str_) { } //深拷贝做法:自己实现一个拷贝构造函数 String::String(const String& other) { str_ = AllocAndCpy(other.str_); } //返回String&:减少拷贝构造函数的调用,返回自身的对象 String& String::operator =(const String &other) { //对象赋值给自身 if (this == &other) return *this; //等号运算符意味着左边的对象已经存在了,所以先销毁 //而拷贝构造函数说明对象还不存在,所以不用先销毁 delete[] str_; str_ = AllocAndCpy(other.str_); return *this; } char* String::AllocAndCpy(char* str) { int len = strlen(str) + 1;//分配这么长的字符串 char* tmp = new char[len];//分配空间 memset(tmp, 0, len); strcpy(tmp, str); return tmp; } void String::Display() { cout<<str_<<endl; }
#include <iostream> using namespace std; class Empty { public: Empty* operator&() { cout<<"AAAA"<<endl; return this; } //const成员函数 const Empty* operator&() const { cout<<"BBBB"<<endl; return this; } }; int main(void) { //p的指针和取地址e是相同的 Empty e; Empty* p = &e; //这里会调用取地址运算符,等价于e.operator&() const Empty e2; const Empty* p2 = &e2;//const在*左边,表示*p2是一个常量 //const在*右边,表示p2是一个常量 //这里的&取地址运算符,进入到了const Empty* operator&() const cout<<sizeof(Empty)<<endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。