1. 程式人生 > >C++基礎學習筆記:類與動態記憶體分配

C++基礎學習筆記:類與動態記憶體分配

實現一個簡單的string類

user.h

//!時間:2017年9月11日(週一)上午
//!內容:類與動態記憶體分配
//!備註:Test類實現簡單的string功能
//!最後修改時間:NULL
//user.cpp
#define _CRTDBG_MAP_ALLOC//記憶體溢位檢測
#include <iostream>
#include "Test.h"
using namespace std;
_CrtMemState s1, s2;//作為引數
int main()
{
	//如果程式從開始加flag這一句,leaks就能自動呼叫而不寫
	//適合用在多個退出點的情況
	//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

	//_CrtMemCheckpoint(&s1);//s1,s2之間可以具體定位
	//_CrtMemCheckpoint(&s2);
	{
		Test one = "this is test!";//構造
		Test two;//預設構造
		two = one;//賦值運算子Test
		two = "test two.";//賦值運算子char*
		Test three(one);//拷貝構造
		cin >> three;
		cout << one << two << three << endl;
	}//析構
	system("pause");
	_CrtDumpMemoryLeaks();//記憶體溢位檢測
	return 0;
}

類定義

//Test.h
//#pragma once
#ifndef _TEST_H
#define _TEST_H
#include <iostream>

class Test
{
private:
	//C++11允許類內初始化
	char *cStr;
	static int count;//定義一個計數變數,監測記憶體的申請和釋放次數
	const static int CINLIMIT=100;//cin>>字串長度限制
public:
	Test(const char *s="");//建構函式:接受一個C字串
	//拷貝與賦值需要逐個成員複製
	Test(const Test&t);//拷貝構造:Test two(one);
	Test&operator=(const Test&t);//賦值運算子:two=one;
	//若沒有定義下面這一句,two="SOME"時,先把some通過建構函式隱式轉換為Test,再呼叫上面那句
	Test&operator=(const char *s);//賦值運算子:two="some";
	void Show();//測試輸出cStr與count;
	~Test();
	friend std::ostream&operator << (std::ostream &os, Test &t);//過載輸入輸出運算子
	friend std::istream&operator >> (std::istream &is, Test &t);
};
#endif
//Test.cpp
#include "Test.h"

int Test::count = 0;
Test::Test(const char *s)
{
	count++;
	//new匹配delete、new[]匹配delete[]
	cStr = new char[strlen(s) + 1];//申請一塊字串大小的記憶體
	strcpy_s(cStr, strlen(s) + 1, s);//拷貝內容
	//std::cout << "構造" << std::endl;
}
Test::Test(const Test&t)
{
	count++;
	cStr = new char[strlen(t.cStr) + 1];
	strcpy_s(cStr, strlen(t.cStr) + 1, t.cStr);
	//std::cout << "拷貝" << std::endl;
}
Test& Test::operator=(const Test&t)
{
	//std::cout << "賦值Test" << std::endl;
	if (this == &t)
		return *this;
	delete[]cStr;//釋放舊的記憶體
	cStr = new char[strlen(t.cStr) + 1];//申請新的記憶體
	strcpy_s(cStr, strlen(t.cStr) + 1, t.cStr);
	return *this;//返回當前物件

}
Test& Test::operator=(const char *s)
{
	//std::cout << "賦值char*" << std::endl;
	delete[]cStr;//釋放舊的記憶體
	cStr = new char[strlen(s) + 1];//申請新的記憶體
	strcpy_s(cStr, strlen(s) + 1, s);
	return *this;//返回當前物件
}
void Test::Show()
{
	std::cout << cStr <<":"<<count<< std::endl;
}
Test::~Test()
{
	delete[]cStr;//釋放記憶體
	--count;
	std::cout << "當前count計數:" << count << std::endl;
}
std::ostream&operator << (std::ostream &os, Test &t)
{
	os << t.cStr;
	return os;
}
std::istream&operator >> (std::istream &is, Test &t)
{
	char temp[Test::CINLIMIT];
	is.get(temp, Test::CINLIMIT);
	if (is)//檢測非法輸入
		t = temp;//呼叫的賦值函式
	while (is&&is.get() != '\n')//清空流:沒有到換行符,但還有大於CINLIMIT的輸入
	{
		//std::cout << "++" << std::endl;
		continue;
	}
	return is;
}