1. 程式人生 > >string類的淺拷貝,深拷貝,寫實拷貝

string類的淺拷貝,深拷貝,寫實拷貝

string類的淺拷貝形式,這種情況下程式會奔潰,因為拷貝構造時共用了一塊空間,但會析構兩次,第一次釋放後就為空

#include <iostream>
#include <string.h>

using namespace std;

class String
{
public:
	String (const char*  str = "")
	{
	     if (str == NULL)
	     {
		    _str = new char[1];
		    _str = '\0';
	      }
	     else
		{
		 _str=new char [strlen(str) +1];
			strcpy(_str, str);
			}
		}

		String (const String& s )
	{
		strcpy(_str,s._str);
	}
	 String&  String:: operator =(const String&  s)
	{
		if (_str != s._str)
		{
			strcpy(_str,s._str);
		}
		return (*this);
	}

		String::~String()
	{
		if ( _str != NULL)
		{
		   delete[] _str;
			_str = NULL;
		}
	}

	private:
		char* _str;
	};
深拷貝第一種形式
#include <iostream>
#include <string.h>
using namespace std;
//  深拷貝簡單版本
class String
{
public:
	String(const char* str = "" )
	{
		if (NULL == str)
		{
			_str = new char [1];
			_str = '\0';
         }
		else {
			_str = new char[strlen(str)+1] ;
			strcpy(_str,str);
		}
	}

	String (const String& s)
		:_str(new char[strlen(s._str)+1] )
	{
		if (this != &s)
		{
			strcpy (_str, s._str) ;
		}
	}

	String& operator = (const String &s)
	{
		String temp(s);
		return temp;
	}

	~String ()
	{
		if (NULL != _str)
		{
			delete [] _str;
			cout << "~String()"<<endl;
          _str = NULL;
		}
	}
private:
	char* _str;
};

第二種形式:
#include <iostream>
#include <string.h>
class String
{
public :
	String(const char* str = "" )
	{
		if (NULL == str)
		{
			_str = new char [1];
			_str = '\0';
         }
		else 
		{
			_str = new char[strlen(str)+1] ;
			strcpy(_str,str);
		}
	}

	String (const String& s)
	:_str(NULL)
	{
		String temp(s._str);
		std::swap (_str , temp._str);
	}

	String& operator = (const String& s)
	{
		String temp(s);
		return temp;
	}

	~String ()
	{
		if (NULL != _str)
		{
			delete [] _str;
			std::cout << "~String()"<<std::endl;
		}
	}


private:
	char *_str;
};

上面兩種形式不會出現問題,但是相同的字串會開闢兩個空間,有一定的浪費

寫實拷貝引用計數int *:這種情況會造成string類的長度不一致,造成記憶體碎片

#include <iostream>
#include <string.h>
using namespace std;
class String 
{
public :
      String (const char* str = "")
		  : _refcount (new int [1])
	  {
         if ( NULL == str)
		 {
			 _str = new char [1];
			 _str = '\0';
		 }
		 else 
		 {
			 _str  = new char [strlen (str)+1];
			 strcpy (_str, str);
		    (*_refcount) = 1;
		}
	  }

	  String (const String&s)
		  :_str(s._str)
		  ,_refcount(s._refcount)
	  {
		  (*_refcount) ++;
	  }
        
	  String& operator = (const String& s )
	  {

		  if (this != &s)
		  {
	         String temp(*this);
		     _str = s._str;
		     _refcount = s._refcount;
		     (*_refcount) ++;
			 if( -- (*temp._refcount) == 0)
			 {
			 delete [] temp._str;
			 delete [] temp._refcount;
			 }
			 (*_refcount ) ++;
		  }
		  return (*this);
	  }

	  ~String ()
	  {
		  if ( --(*_refcount) == 0 && _str!= NULL)
		  {
			  delete [] _str;
			  delete []_refcount;
			  _str = NULL;
			  cout<<"~String ()"<< endl;
		  }
	  }
private:
	  char *_str;
      int*  _refcount;
};


寫實拷貝:

#include <iostream>
#include <string.h>
using namespace std;
class String 
{
public :
	String (const char* str = "")
		:_str(new char [strlen(str)+5])
	{
		if (NULL == str)
		{
			_str = new char(5);
			*(int*)_str= 1;
			_str += 4;
			_str = '\0';
		}
		else 
		{
		     *(int*)_str= 1;
		     _str += 4;
			 strcpy (_str, str);
		}		 
	}

	String (const String& s)
		:_str(s._str)
	{
		(*(int*)(_str-4)) ++;
	}

	String operator = (const String& s)
	{
		if (_str != s._str)
		{
            Release();
			_str = s._str;
			(*(int*)(_str-4)) ++;
		}
		return (*this);
	}


	~String ()
	{
		if ( -- (*(int*)(_str-4)) == 0 )
		{
			delete [] (_str-4 );
			_str = NULL;
			cout <<"~String ()"<<endl;
		}
	}


	void Release ()
	{
		if ( --(*(int*)(_str-4)) == 0)
		{
			delete [](_str-4);
		}
	}

	friend ostream& operator<<(ostream& cout, String& s)
	{
		cout << s._str << endl;
		return cout;
	}

	char operator[] (const int index)
	{
		return _str[index];
	}

private:
	char* _str;
};

相關推薦

【C++】c++String拷貝拷貝

在瞭解深拷貝以及寫時拷貝之前,我們先來了解什麼是淺拷貝,看下面程式碼: class String { public: String(char* ptr = "") :_ptr(new char[strlen(ptr)+1])

JAVA#String相關轉換(字元陣列位元組陣列包裝)'札記

public class StringTransformer { public static void main(String[] args) { String s1="2324"; int s1_1=Integer.parseInt(s1);//包裝類

String的普通建構函式,解構函式,拷貝建構函式和賦值函式

編寫類String的建構函式、解構函式和賦值函式,已知類String的原型為: class String {  public:   String(const char *str = NULL); // 普通建構函式   String(const String &ot

String詳解(拷貝拷貝引用計數寫時拷貝

String類:標準庫型別string類表示可變長的字元序列,定義在std中,專門用來管理字串,下面一起看下它的重要考點。 一,淺拷貝       所謂淺拷貝,是指原物件與拷貝物件公用一份實體,僅

string拷貝拷貝寫實拷貝

string類的淺拷貝形式,這種情況下程式會奔潰,因為拷貝構造時共用了一塊空間,但會析構兩次,第一次釋放後就為空 #include <iostream> #include <str

C++進階--擁有資源控制代碼的(拷貝拷貝虛建構函式)

// Person通過指標擁有string class Person { public: Person(string name) { pName_ = new string(name); } ~Person() { delete pName_; } void printName() { c

C++進階--擁有資源句柄的(拷貝拷貝虛構造函數)

拷貝 保存 ... 代碼 cpp 不同的 容易 淺拷貝 聲明 // Person通過指針擁有string class Person { public: Person(string name) { pName_ = new string(name); } ~Per

引用賦值拷貝拷貝

lan art csdn 理解 article 淺拷貝和深拷貝 blank .net hang 三種引用: http://blog.csdn.net/XIAXIA__/article/details/41652057 深拷貝和淺拷貝的理解: http://blog.csdn

python的復制拷貝拷貝的區別(轉)

pla bsp space 數據 深拷貝 淺拷貝 deepcopy 拷貝 tro 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是拷貝了這個對象的引用 一般有三種方法, alist=[1,2,

string的深淺拷貝寫時拷貝

{} end spa return 崩潰 clas hello str 深拷貝 string類的深淺拷貝,寫時拷貝淺拷貝:多個指針指向同一塊空間,多次析構同一塊內存空間,系統會崩潰。(淺拷貝就是值拷貝)深拷貝:給指針開辟新的空間,把內容拷貝進去,每個指針都指向自己的內存空間

python的復制拷貝拷貝的區別

一個 對象賦值 source 深拷貝 對象的引用 數據 拷貝 也會 方法 寫在前面: python中的.copy()拷貝和[:]拷貝皆為淺拷貝 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是

拷貝拷貝的實現方式、區別;deepcopy如果你來設計如何實現(一)

.net cal ict idt 變更 tmp png nbsp ocp 淺拷貝與深拷貝的實現方式、區別;deepcopy如果你來設計,如何實現; copy淺拷貝:沒有拷貝子對象,所以原始數據改變,子對象改變 deepcopy深拷貝:包含對象裏面的子對象的拷貝,所以原始對

pyhton之拷貝(copy)和拷貝(deepcopy)詳解舉例說明

python copy deepcopy a = [1, 2, [‘a‘, ‘b‘]]a1 = ab = copy.copy(a)c = copy.deepcopy(a)a.append(3)a[2].append(‘c‘)print(a)print(a1)print(b)print(c) 結果:

賦值拷貝拷貝

怎麽 嘗試 world 賦值 app 第一個 code 以及 不可 一、賦值str例 a=‘hello‘ b=‘hello‘ c=a print(id(a),id(b),id(c)) #2518845789440 2518845789440 251884578

賦值拷貝拷貝自己的理解

賦值 a=[1,2,3,4,[35,44,66]] b=a b[0]=11 print(a) print(b) #[11, 2, 3, 4, [35, 44, 66]] #[11, 2, 3, 4, [35, 44, 66]]   淺拷貝 import cop

js中物件引用拷貝拷貝--示例

1. 物件引用 var a = {name:'wanger'} var b = a ; a===b // true b.name = 'zhangsan' a.name //'zhangan' 2 .淺拷貝 var a = {name:'wanger'} var b = Object.a

拷貝建構函式拷貝拷貝

  深淺拷貝的區別:     淺拷貝是將原始物件中的資料型欄位拷貝到新物件中去,將引用型欄位的“引用”複製到新物件中去,不把“引用的物件”複製進去,所以原始物件和新物件引用同一物件,新物件中的引用型欄位發生變化會導致原始物件中的對應欄位也發生

Python的賦值拷貝拷貝的區別

在python中,物件賦值實際上是物件的引用。當建立一個物件,然後把它賦給另一個變數的時候,python並沒有拷貝這個物件,而只是拷貝了這個物件的引用 一般有三種方法, alist=[1,2,3,["a","b"]]   (1)直接賦值,傳遞物件的引用而已,原始列表改變,被

python賦值拷貝拷貝

>>> a = 1 >>> b = a >>> a = 2 >>> a 2 >>> b 1 >>> 你將 1 賦給 a 變數,然後拷貝 a 中的值,將它賦給變數 b。當稍 後將

JavaScript中拷貝拷貝棧堆詳解

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/weixin_40983119/article/details/82995151 簡單來說,JavaScript中單個等於號的賦值就是拷貝,但是呢這個這個賦值可以分為兩種,一種是賦的是資料,一種是賦