第一部分連接https://blog.51cto.com/14232799/2447326
創(chuàng)新互聯(lián)是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號開發(fā),軟件開發(fā),微信小程序開發(fā),十多年建站對公路鉆孔機(jī)等多個(gè)行業(yè),擁有多年的網(wǎng)站營銷經(jīng)驗(yàn)。
在第一步之后緊接著的就該是模擬實(shí)現(xiàn)部分,這一部分主要是體現(xiàn)自己對第一部分的掌握情況。強(qiáng)烈推薦和我一樣在學(xué)習(xí)String的朋友們自己動(dòng)手實(shí)現(xiàn)一下。因?yàn)樵诿嬖囍校嬖嚬倏傁矚g讓我們自己來模擬實(shí)現(xiàn)string類。
自己來實(shí)現(xiàn)String最主要是實(shí)現(xiàn)String類的構(gòu)造、拷貝構(gòu)造、賦值運(yùn)算符重載(第一部分operator開頭的方法)以及析構(gòu)函數(shù)。
以下是我完成的基礎(chǔ)模擬實(shí)現(xiàn)
#include<iostream>
#include<assert.h>
using namespace std;
namespace self{
class string{
public:
string(const char* s = " "){
if (s == nullptr){
assert(false);
return;
}
_s = new char[strlen(s) + 1];
strcpy(_s, s);
}
~string(){
if (_s){
delete[] _s;
_s = nullptr;
}
}
private:
char* _s;
};
}
int main(){
self::string k = "hello";
self::string i("world");
self::string m;
//self::string l(k);
return 0;
}
以上就是沒有重載賦值運(yùn)算符且沒有顯式定義拷貝構(gòu)造函數(shù)的string類模擬實(shí)現(xiàn)?;就暾哪M實(shí)現(xiàn)會在本篇文章的最后給出(當(dāng)然免不了有紕漏,若是發(fā)現(xiàn)請各位大佬提醒)
上面的代碼中的main函數(shù)中有一句注釋語句 //self::string l(k); 我將其注釋是因?yàn)槿绻尤脒@一句代碼程序就會運(yùn)行崩潰?。。?!
程序崩潰的原因是: 當(dāng)我們不去顯式定義拷貝構(gòu)造方法的時(shí)候,系統(tǒng)就會生成默認(rèn)的拷貝構(gòu)造函數(shù),這種拷貝構(gòu)造函數(shù)是一種淺拷貝,最終結(jié)果就是導(dǎo)致 對象l和對象k在共用同一塊內(nèi)存空??雌饋硭坪鯖]什么問題?
但是!當(dāng)函數(shù)結(jié)束時(shí),在調(diào)用析構(gòu)函數(shù)的操作上就會出現(xiàn)大問題。
原本的話,每一個(gè)對象都會調(diào)用一次析構(gòu)函數(shù)來清理自己占用的空間。但是當(dāng)兩個(gè)對象所占用的是同一塊空間時(shí),一個(gè)對象調(diào)用完析構(gòu)函數(shù)后另一個(gè)對象調(diào)用析構(gòu)函數(shù)的時(shí)候,就會生同一塊空間被釋放多次的程序錯(cuò)誤!從而引起程序崩潰!
所以說在以上這個(gè)的代碼中不可以使用拷貝構(gòu)造方法。這個(gè)問題也就引出了下一個(gè)要總結(jié)的部分:淺拷貝和深拷貝
1.淺拷貝
此處只是給個(gè)定義:
淺拷貝:也稱位拷貝,編譯器只是將對象中的值拷貝過來。如果對象中管理資源,最后就會導(dǎo)致多個(gè)對象共享同一份資源,當(dāng)一個(gè)對象銷毀時(shí)就會將該資源釋放掉,而此時(shí)另一些對象不知道該資源已經(jīng)被釋放,以為還有效,所以 當(dāng)繼續(xù)對資源進(jìn)項(xiàng)操作時(shí),就會發(fā)生發(fā)生了訪問違規(guī)。所以要解決淺拷貝問C++中引入了深拷貝。
(第二部分的string模擬事先就是個(gè)例子)
放個(gè)圖片占位:
2.深拷貝
“如果一個(gè)類中涉及到資源的管理,其拷貝構(gòu)造函數(shù)、賦值運(yùn)算符重載以及析構(gòu)函數(shù)必須要顯式給出。一般情況都是按照深拷貝方式提供”
上面這句話是真理!
首先給出深拷貝一般在string'類中的實(shí)現(xiàn):
String(const String& s)
: _str(new char[strlen(s._str)+1]) // 看見這一步開辟空間就知道是深拷貝了
{
strcpy(_str, s._str);
}
再來說深拷貝的定義:
每個(gè)string都需要空間來存放字符串,而當(dāng)使用一個(gè)string類對象來構(gòu)造另一個(gè)string類對象。就用到了深拷貝:給每個(gè)對象獨(dú)立分配資源,保證多個(gè)對象之間不會因共享資源而造成空間多次釋放而造成的程序奔潰問題。
三.String中賦值運(yùn)算符重載
1.先給出幾種在string中常用的賦值運(yùn)算符重載:
<1> <<
ostream& bit::operator<<(ostream& _cout, const self::String& s)
{
cout << s._str;
return _cout;
}
對于<<的重載算是比較特殊的了,因?yàn)闀玫給stream類型,所以在這里展開說明一下:
ostream是output stream的簡稱,即輸出流。一個(gè)典型的輸出流對象就是在C++中標(biāo)準(zhǔn)輸出流cout。
在C++中,很少自定義ostream的對象,更多的是直接使用cout。
ostream這個(gè)類型,往往出現(xiàn)在<<操作重載中,作為某個(gè)類的友元函數(shù)出現(xiàn)。
比如對于class A, 可以定義ostream & operator << (ostream &os, const A& a);
這樣在調(diào)用A的對象var時(shí),就可以這樣使用cout << var ;
<2> =
String& operator=(String s)
{
swap(_str, s._str);
return *this;
}
<3> +=
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
<4> [ ]
char& operator[](size_t index)
{
assert(index < _size);
return _str[index];
}
namespace key
{
class String
{
public:
typedef char* iterator;
public:
String(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity+1];
strcpy(_str, str);
}
String(const String& s)
: _str(nullptr)
, _size(0)
, _capacity(0)
{
String tmp(s);
this->Swap(tmp);
}
String& operator=(String s)
{
this->Swap(s)
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
/////////////////////////////////////////////////////////////////
// iterator
iterator begin() {return _str;}
iterator end(){return _str + _size;}
/////////////////////////////////////////////////////////////////
// modify
void PushBack(char c)
{
if (_size == _capacity)
Reserve(_capacity*2);
_str[_size++] = c;
_str[_size] = '\0';
}
String& operator+=(char c)
{
PushBack(c);
return *this;
}
void Clear()
{
_size = 0;
_str[_size] = '\0';
}
void Swap(String& s)
{
swap(_str, s._str);
swap(_size, s._size);
swap(_capacity, s._capacity);
}
const char* C_Str()const
{
return _str;
}
size_t Size()const
size_t Capacity()const
bool Empty()const
void Resize(size_t newSize, char c = '\0')
{
if (newSize > _size)
{
// 如果newSize大于底層空間大小,則需要重新開辟空間
if (newSize > _capacity)
{
Reserve(newSize);
}
memset(_str + _size, c, newSize - _size);
}
_size = newSize;
_str[newSize] = '\0';
}
void Reserve(size_t newCapacity)
{
// 如果新容量大于舊容量,則開辟空間
比特科技
if (newCapacity > _capacity)
{
char* str = new char[newCapacity + 1];
strcpy(str, _str);
// 釋放原來舊空間,然后使用新空間
delete[] _str;
_str = str;
_capacity = newCapacity;
}
}
char& operator[](size_t index)
{
assert(index < _size);
return _str[index];
}
const char& operator[](size_t index)const
{
assert(index < _size);
return _str[index];
}
private:
friend ostream& operator<<(ostream& _cout, const bit::String& s);
private:
char* _str;
size_t _capacity;
size_t _size;
};
}
ostream& key::operator<<(ostream& _cout, const bit::String& s)
{
cout << s._str;
return _cout;
}
網(wǎng)站題目:C++STL主要組件之String總結(jié)(第二部分深、淺拷貝問題以及賦值運(yùn)算符重載)
URL標(biāo)題:http://jinyejixie.com/article40/pppheo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站設(shè)計(jì)、定制開發(fā)、微信公眾號、網(wǎng)站排名、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)