C++初阶-vector类的模拟实现

这篇具有很好参考价值的文章主要介绍了C++初阶-vector类的模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、经典的vector类问题

C++ STL中的vector就类似于C语言当中的数组,但是vector又拥有很多数组没有的接口,使用起来更加方便。
相比于STL中的string,vector可以定义不同的数据类型。

1.1 前期准备

迭代器的本质可以暂时看作是指针,模拟实现vector,需要定义三个指针:指向起始位置_start,指向最后一个有效元素的下一个位置_finish,指向容器最后一个位置_end_of_storage
C++初阶-vector类的模拟实现,c++,开发语言

namespace zl {  //自定义命名空间
	template<class T>     //定义模板类型
	class vector{
	public:
		typedef T* iterator;   //迭代器  等价于  T 类型指针
	private:
		iterator _start;   //空间起始位置
		iterator _finish;  //最后一个有效元素的下一个位置
		iterator _end_of_storage;  //最后一个容量空间位置
	};
}

二、vector的默认成员函数

2.1 构造函数

2.1.1 无参构造

构造一个空vector,size和capacity为0,将_start,_finish,_end_of_storage都置为空指针即可

vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}

2.1.2 构造具有n个对象值为val的容器(数据类型为模板类型T)

vector(size_t n, const T& val = T())
{
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
	
	reserve(n);
	for (size_t i = 0; i < n; ++i)
	{
		push_back(val);
	}
}

vector(int n, const T& val = T())
{
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
	
	reserve(n);
	for (int i = 0; i < n; ++i)
	{
		push_back(val);
	}
}

2.1.3 拷贝构造

传统写法
(1)新开辟一块和v同样容量的空间,更新_startt,_finish,_end_of_storage
(2)将v中的数据拷贝到新开辟的空间中

vector(const vector<T>& v)
{
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
	
	//reserve(v.capacity());
	_start = new T[v.capacity()];
	//memcpy(_start, v._start, sizeof(T) * v.size());
	for (size_t i = 0; i < v.size(); ++i)
	{
		_start[i] = v._start[i];
	}

	_finish = _start + v.size();
	_end_of_storage = _start + v.capacity();
}

现代写法
使用范围for进行遍历,变量e是v中元素的拷贝,如果v中元素是需要深拷贝的自定义类型,会调用拷贝构造函数构造e,从而使e和v中元素所指向的空间不一样(auto& e:v也可以,因为push_back在实现的时候还会调用深拷贝类型的赋值运算符重载)

vector(const vector<T>& v)
{
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
	reserve(v.capacity());
	for (auto e : v)
	{
		push_back(e);
	}
}

新写法

vector(const vector<T>& v)
{
	vector<T> tmp(v.begin(), v.end());  //定义临时对象--调用迭代器构造方法
	swap(tmp);   //进行资源交换
}

2.2 swap(operator=需要用)

调用全局的swap,交换指针,其为内置类型,无需深拷贝,代价相比于直接调用库里面函数交换比较小

void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_end_of_storage, v._end_of_storage);
}

2.3 复制重载operator=

传统写法
(1)释放原空间,新开一块容量和v一样大的空间,更新_start,_finish,_end_of_storage
(2)将v中的数据拷贝到新空间中

vector<T>& operator=(const vector<T>& v)
{
	if (this != &v)
	{
		delete[]_start; // 释放原空间
		_start = new T[v.capacity()]; // 开辟新空间
		for (size_t i = 0; i < v.size(); i++) // 拷贝数据
		{
			_start[i] = v[i];
		}
		_finish = _start + v.size(); // 更新_finish
		_endofstorage = _start + v.capacity(); // 更新_capacity
	}
	return *this;
}

现代写法
(1)调用拷贝构造函数生成tmp对象
(2)分别交换tmp和this的_start,_finish,_end_of_storage

vector<T>& operator=(const vector<T>& v)
{
	if (this != &v) // 防止自己给自己赋值
	{
		vector<T> tmp(v); // 拷贝构造tmp对象
		swap(tmp); // 交换_start,_finish, _endofstorage
	}
	return *this;
}
vector<T>& operator=(vector<T> v) // 拷贝构造v对象
{
	swap(v); // 交换_start,_finish, _endofstorage
	return *this;
}

2.4 析构函数

将空间释放掉,_start,_finish,_end_of_storage置为空指针

~vector()
{
	delete[] _start;
	_start = _finish = _end_of_storage = nullptr;
}

三、vector的三种遍历方式

3.1 size和capacity

size返回容器中有效数据的个数,用_finish-_start即可

size_t size() const
{
	return _finish - _start;
}

capacity返回容器的容量,用_end_of_storage-_start即可

size_t capacity() const
{
	return _end_of_storage - _start;
}

3.2 operator[]遍历

返回底层数组对应位置的引用即可,需要用const和非const两个版本

T& operator[](size_t pos)
{
	assert(pos < size());
	return _start[pos];
}

const T& operator[](size_t pos) const
{
	assert(pos < size());
	return _start[pos];
}

3.3 迭代器iterator遍历和范围for

迭代器也需要写const和非const两个版本,且一个容器只要支持迭代器,就可以用范围for操作,因为范围for本质也是迭代器

iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

const_iterator begin() const
{
	return _start;
}

const_iterator end() const
{
	return _finish;
}

四、vector相关的增容和删除

4.1 reserve

(1)当n大于对象当前的capacity时,将capacity扩大到n或大于n
(2)当n小于对象当前的capacity时,什么也不做
增容前就需要算出size的大小
因为增容涉及新和旧空间的问题,比如_finish=tmp+size(),而size的求法是用_finish-_start,但_start已指向新空间,可_finish还是指向旧空间,两块不连续的空间相减就是随机值了,故要在增容之前就把大小算出来,不然增容之后的大小就是随机值了。
reserve需要更新_finish
因为_finish是指针,如果一个对象它上来就reserve保存一定容量,然后直接扩容,但是插入数据肯定涉及*_finish操作,若不更新_finish,_finish初始化为nullptr就非法访问内存了,故reserve中也要更改_finish。
不能使用memcpy拷贝数据
因为增容中使用了memcpy,memcpy导致了问题的出现,因为memcpy是按字节拷贝的,它本质上造成了浅拷贝问题,memcpy使新旧空间都指向了一份数据,旧空间释放后,它指向的对应数据也被释放,而新空间指针还是指向这份旧空间,这就造成了非法访问,所以新空间与旧空间不应该指向同一份数据,应该不用memcopy,写成深拷贝(将旧空间的每个值赋值给新空间对应的每个值就好了,就很实现深拷贝了,指向不同的数据)
C++初阶-vector类的模拟实现,c++,开发语言

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t sz = size();
		T* tmp = new T[n];
		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T) * size());
			for (size_t i = 0; i < sz; ++i)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}

		_start = tmp;
		_finish = tmp + sz;
		_end_of_storage = tmp + n;
	}
}

4.2 resize

(1)当n<size时,直接将_finish=_start+n(将有效数据长度缩小)即可
(2)当size<n<=capacity时,将有效数据的长度增加到n,增加出来的有效数据内容是val
(3)当n>capacity时,先调用上面的reserve函数进行增容,再将有效数据的长度增加到n,增加出来的有效数据内容是val

void resize(size_t n,T val=T())
		{
			if (n < size())
			{
				//删除数据
				_finish = _start + n;

			}
			else
			{
				if (n > capacity())
					reserve(n);

				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}

			}
		}

4.3 push_back

尾插数据,首先要检查是否已满,已满则进行增容,增容后尾插即可

void push_back(const T& x)
{
	if (_finish == _end_of_storage)
	{
		reserve(capacity() == 0 ? 4 : capacity() * 2);
	}
	*_finish = x;
	++_finish;
}

4.4 pop_back

尾插时,首先要判断容器是否为空,若为空,则断言报错,不为空,_finish–即可

void pop_back()
{
	assert(!empty());

	--_finish;
}

4.5 insert

(1)容量不够,先增容,增容前先记录pos-_start的值,否则增容之后,pos还指向原来已经被释放的空间
(2)将pos位置往后的数据往后挪一位,在pos位置插入值val
为什么需要提前计算出len
有迭代器失效的问题,因为pos是迭代器类型,扩容前指向旧空间的某一位置,而reserve调用后会扩容,而我们是扩容完才插入数据的,此时pos无效,因为旧空间已经释放了,它这个迭代器还指向那里就失效了,故我们要更新pos位置,使它指向新空间,所以要先算len,即原pos的位置

//迭代器失效:扩容引起,野指针问题
iterator insert(iterator pos, const T& val)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start;
		reserve(capacity() == 0 ? 4 : capacity() * 2);

		//扩容后更新pos,解决pos失效的问题
		pos = _start + len;
	}

	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = val;
	++_finish;

	return pos;
}

4.6 erase

erase是返回被删除数据的下一个位置,当要被删除的数据被删除了,erase原地不动的话,就已自动指向了下一位置,因为那个数据被删除了

iterator erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);

	iterator start = pos + 1;
	while (start != _finish)
	{
		*(start - 1) = *start;
		++start;
	}
	--_finish;

	return pos;
}

4.7 empty

判断是否为空文章来源地址https://www.toymoban.com/news/detail-759678.html

bool empty()
{
	return _start == _finish;
}

五、完整代码

5.1 vector.h

#pragma once
#include <assert.h>


namespace zl
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		vector()
			/*:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)*/
		{}

		vector(size_t n, const T& val = T())
		{
			/*:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)*/
			reserve(n);
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		vector(int n, const T& val = T())
		{
			/*:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)*/
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		/*vector(const vector<T>& v)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}*/


		//vector(const vector<T>& v)
		//{
		//	//reserve(v.capacity());
		//	_start = new T[v.capacity()];
		//	//memcpy(_start, v._start, sizeof(T) * v.size());
		//	for (size_t i = 0; i < v.size(); ++i)
		//	{
		//		_start[i] = v._start[i];
		//	}

		//	_finish = _start + v.size();
		//	_end_of_storage = _start + v.capacity();
		//}

		vector(const vector<T>& v)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}

		//void swap(vector& v)
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}

		//v1=v2
		//vector& operator=(vector v)
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}


		//[first,last)
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}


		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		void resize(size_t n,T val=T())
		{
			if (n < size())
			{
				//删除数据
				_finish = _start + n;

			}
			else
			{
				if (n > capacity())
					reserve(n);

				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}

			}
		}



		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * size());
					for (size_t i = 0; i < sz; ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}

				_start = tmp;
				_finish = tmp + sz;
				_end_of_storage = tmp + n;
			}
		}

		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());

			--_finish;
		}

		//迭代器失效:扩容引起,野指针问题
		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _start);
			assert(pos <= _finish);

			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);

				//扩容后更新pos,解决pos失效的问题
				pos = _start + len;
			}

			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = val;
			++_finish;

			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			iterator start = pos + 1;
			while (start != _finish)
			{
				*(start - 1) = *start;
				++start;
			}
			--_finish;

			return pos;

		}



		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		size_t size() const
		{
			return _finish - _start;
		}

		bool empty()
		{
			return _start == _finish;
		}

		T& operator[](size_t pos)
		{
			assert(pos < size());
			return _start[pos];
		}

		const T& operator[](size_t pos) const
		{
			assert(pos < size());
			return _start[pos];
		}

	private:
		iterator _start= nullptr;
		iterator _finish= nullptr;
		iterator _end_of_storage= nullptr;
	};

	void func(const vector<int>& v)
	{
		for (size_t i = 0; i < v.size(); ++i)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		vector<int>::const_iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_vector1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);

		func(v1);

		for (size_t i = 0; i < v1.size(); ++i)
		{
			cout << v1[i] << " ";
		}
		cout << endl;

		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		//v1.pop_back();
		//v1.pop_back();
		//v1.pop_back();

		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	//template<class T>
	//void f()
	//{
	//	T x = T();
	//	cout << x << endl;
	//}

	//void test_vector2()
	//{
	//	//内置类型有没有构造函数
	//	//int i = int();
	//	//int j = int(1);
	//	int* pi = int* ();

	//	f<int>();
	//	f<int*>();
	//	f<double>();
	//}


	void test_vector2()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);

		cout << v1.size() << endl;
		cout << v1.capacity() << endl;

		v1.resize(10);

		cout << v1.size() << endl;
		cout << v1.capacity() << endl;

		func(v1);

		v1.resize(3);

		func(v1);
	}

	void test_vector3()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		func(v1);

		v1.insert(v1.begin(), 0);
		func(v1);

		auto pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())
		{
			//v1.insert(pos, 30);
			pos=v1.insert(pos, 30);
		}
		func(v1);

		//insert以后我们认为pos失效了,不能再使用
		//(*pos)++;
		func(v1);
	}


	void test_vector4()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		func(v1);

		auto pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())
		{
			v1.erase(pos);
		}

		//erase以后,pos是否失效
		//pos失效了,不能访问并且进行强制检查
		//失效,不要访问,行为结果未定义   根据具体编译器实现有关,在g++中没报错 但是在vs下进行报错
		//(*pos)++;

		func(v1);
	}


	void test_vector5()
	{
		vector<int> v1;
		v1.push_back(10);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		func(v1);

		//要求删除所有的偶数
		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			if (*it % 2 == 0)
			{
				it=v1.erase(it);
			}
			else
			{
				++it;
			}
		}
		func(v1);
	}


	void test_vector6()
	{
		//vector<int> v1(10u,5);    //u表示这个字面量为无符号
		vector<int> v1(10,5);   

		func(v1);

		vector<int> v2(v1.begin() + 1, v1.end() - 1);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		std::string s1("hello");
		vector<int> v3(s1.begin(), s1.end());
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;


		int a[] = {30,20,10};
		vector<int> v4(a,a+3);
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;


		v1.insert(v1.begin(), 10);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		sort(v1.begin(), v1.end());
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;


		for (auto e : a)
		{
			cout << e << " ";
		}
		cout << endl;

		//sort(a, a + sizeof(a) / sizeof(int));   //默认是升序<     降序>

		//greater<int> g;
		//sort(a, a + sizeof(a) / sizeof(int), g);

		sort(a, a + sizeof(a) / sizeof(int), greater<int> ());

		sort(a, a + sizeof(a) / sizeof(int));   
		for (auto e : a)
		{
			cout << e << " ";
		}
		cout << endl;
	}


	void test_vector7()
	{
		vector<int> v1(10, 5);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v2(v1);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;


		vector<std::string> v3(3, "1111111111111111");
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;


		vector<std::string> v4(v3);
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;

	}

}


5.2 test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<functional>
#include<string>
#include<vector>
using namespace std;
#include "vector.h"

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}

	~A()
	{
		cout << "A()" << endl;
	}

};


int main()
{
	/*vector<int>::iterator it;
	cout << typeid(it).name() << endl;*/

	//zl::test_vector1();
	//zl::test_vector2();
	//zl::test_vector3();
	//zl::test_vector4();
	//zl::test_vector5();
	//zl::test_vector6();
	zl::test_vector7();


	//A a1;
	A();     //匿名对象生命周期只在当前一行,因为这行之后没人会用它了
	//const A& xx = A();    //const引用会延长匿名对象的生命周期到引用对象域结束,因为以后用xx就是用匿名对象
	//A a2;

	return 0;
}

到了这里,关于C++初阶-vector类的模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】第八站:string类的模拟实现

    目录 string类的模拟实现 经典的string类问题 浅拷贝 深拷贝 写时拷贝(了解) 构造函数 string的全缺省的构造函数: string的拷贝构造函数 传统写法 现代写法 string的赋值重载函数 传统写法 现代写法 string的无参构造函数: 遍历函数 operator[ ] 迭代器 迭代器的底层实现begin和end:

    2024年04月28日
    浏览(39)
  • 【C++练级之路】【Lv.7】【STL】vector类的模拟实现

    快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C++》 远方有一堆篝火,在为久候之人燃烧! 关于STL容器的学习,我们来到了运用 最广泛、最常见的vector 。有了之前关于string的学习,我们对容器设计有了一个大概的了解,而今天在熟悉的基础上去探求

    2024年01月24日
    浏览(53)
  • 【C++初阶】STL详解(二)string类的模拟实现

    本专栏内容为:C++学习专栏,分为初阶和进阶两部分。 通过本专栏的深入学习,你可以了解并掌握C++。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:C++ 🚚代码仓库:小小unicorn的代码仓库🚚 🌹🌹🌹关注我带你学习编程知识 注:为了防止与标准库当中的string类产生命名冲

    2024年02月05日
    浏览(57)
  • 【C++】vector类的模拟实现(增删查改,拷贝构造,赋值运算,深浅拷贝)

    🌏博客主页: 主页 🔖系列专栏: C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 😍期待与大家一起进步! 我们模拟vector是用迭代器(start,end,endofstorage)来控制增删查改操作的 1普通构造 2迭代器构造 3初始化字符构造 4拷贝构造: 1当前大小(size()) 2总体容量(capacity()) 1begin()

    2024年02月15日
    浏览(60)
  • C++初阶之一篇文章让你掌握vector(模拟实现)

    模拟实现vector是为了深入理解和学习C++标准库中vector容器的工作原理和实现细节。 vector是C++标准库中最常用的容器之一,它提供了动态数组的功能,并且具有自动扩容和内存管理的特性,使得在使用时非常方便。 模拟实现vector有以下几个优点: 学习数据结构与算法 :实现

    2024年02月14日
    浏览(45)
  • C++的vector类的简单实现

    下面代码是有关于 vector 的一些基础实现,和库里的函数可能有较大的不同,但是基本可以实现 vector 的很多功能。

    2024年02月11日
    浏览(39)
  • C++初阶 日期类的实现(下)

    目录 一、输入输出(,)重载的实现 1.1初始版  1.2友元并修改 1.2.1简单介绍下友元 1.2.2修改 1.3重载 二、条件判断操作符的实现 2.1==操作符的实现 2.2!=操作符的实现 2.3操作符的实现 2.4=,=,操作符的实现 三、日期-日期的实现 四、下期预告 前言:C++初阶系列,每一期博主都会使用

    2024年02月04日
    浏览(36)
  • C++初阶 日期类的实现(上)

    目录 一、前置准备 1.1获得每月的天数 1.2获得每年的天数 1.3构造函数,析构函数和拷贝构造函数 二、日期与天数的+,-,+=,-=实现 2.1+=运算符重载 2.2+运算符的实现 2.3-=运算符的实现 2.4-运算符的实现 三、++,--的实现 3.1前置++,后置++的实现 3.2前置--和后置--的实现 四、下期预告

    2024年02月05日
    浏览(38)
  • C++初阶--类与对象--const成员和日期类的实现

    将const修饰的成员函数称之为const成员函数。 在一个成员函数里面,对于this指针指向的对象,是隐藏式的,没有办法用常规的方法去修饰它,所以我们是这样进行修饰的: 注意事项: date.h date.cpp 这里采用多文件编程的方式,所以在date.cpp中,是在Date类外使用的,需要加上作

    2024年02月05日
    浏览(49)
  • C++ 模拟实现vector

    目录 一、定义 二、模拟实现 1、无参初始化 2、sizecapacity 3、reserve 4、push_back 5、迭代器 6、empty 7、pop_back 8、operator[ ] 9、resize 10、insert 迭代器失效问题 11、erase 12、带参初始化 13、迭代器初始化 14、析构函数 15、深拷贝 16、赋值运算符重载 完整版代码测试代码 本次参考SGI版

    2024年02月04日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包