STL手撕

简易vector:

vector的操作:

push_back(), pop_back(), 

单端的容器

实现一个简易的vector:

#include
using namespace std;

template
class MyVector
{
public:
	typedef T value;
	typedef T* iterator;//vector里面的itreator本质就是一个指针
	typedef T& reference;

	MyVector(int len = 0) :m_len(len), m_Data(nullptr), start(nullptr), pos(0)
	{
		if (len > 0)
		{
			//创建一个数组
			m_Data = new value[len];
			start = m_Data;
		}
	}
	~MyVector()
	{
		delete[]m_Data;
	}
	void push_back(const value& v)
	{
		if (m_len != pos)
		{
			*(start + pos) = v;
			pos++;
		}
		else
		{
			cout << "越界" << endl;
		}

	}
	inline value pop_back()
	{
		--pos;
		return *(start + pos);
	}
	int size()
	{
		return this->m_len;
	}
	iterator begin()
	{
		return this->start;
	} 
	iterator end()
	{
		return this->start + pos;
	}
	value& operator[](int n)//[]进行重载,传一个引用才能对vector里面的值进行修改,引用形参绑定他的初始化对象
	{
		if (n <= pos)
		{
			return *(start + n);
		}
		else
		{
			cout << "数组越界" << endl;
		}
	}

protected:
	iterator m_Data;
	iterator start;
	int m_len;
	int pos;
};

template
ostream& operator<<(ostream& cout, MyVector vec)
{
	for (int i = 0; i < vec.size(); i++)
	{
		cout << vec[i] << " ";
	}
	return cout;
}
int main()
{
	MyVector vec(10);
	for (int i = 0; i < vec.size(); i++)
	{
		vec.push_back(i);
	}
	for (MyVector::iterator it = vec.begin(); it != vec.end(); it++)
	{
		cout << *it << " ";
	}
}

 什么是右值引用?移动语义源码剖析

什么是左值和右值?

按照我们常规理解左值就是在等号左边的值,右值是等号右边的值。如果你要这么理解,你就会发现遇到++ii++这一类的语句你就开始混乱了!

其实左值和右值是我们习惯性的叫法,他的全拼应该是:
左值是:locator value(可寻址的数据)
右值是:read value(不可寻址的数据或用来读的数据)

左值、右值、左值引用和右值引用_左值右值_四库全书的酷的博客-CSDN博客

举例说明:

右值:x++

//x++;这个从底层去分析:

//x++会产生一个临时变量,用来保存x+1的值,

//等到语句结束,将x+1赋值给x.

//但是语句没结束时,这个临时变量时在寄存器中保存的,一个计算结果的临时变量,

//此时是不可寻址的!!即右值。x=x+1

左值:++x

//这里面++x是直接对x自增,我们得到的值就是x的值,

左值引用 

1 左值引用得到的就是还是一个左值。

2 左值引用,它的本质就是指针常量

3 左值引用就是一个不能变的指针,所以在定义引用的时候就需要给它初始化,因为他之后就不可以改变了。

STL手撕_第1张图片

非常量引用的初始值必须为左值,很明显5不是左值,没有地址可以寻找

 STL手撕_第2张图片

 STL手撕_第3张图片

 右值引用 (important!!!)

右值引用的使用常常在自定义类中,可以查看该博文去理解。

右值引用操作符为 “&&”;
右值引用得到的是一个左值。
右值引用通常将一个临时变量拿过来用。
右值引用最主要的功能是解决的是自定义类重复构造冗余的问题。

#include
#include
using namespace std;

class Student
{
public:
	char* name;
	int size;
	
	Student(int size = 0) :size(size), name(nullptr)//构造函数
	{
		if (size > 0)
		{
			name = new char[size];
			for (int i = 0; i < size; i++)
			{
				name[i] = 'a';
			}
		}
		cout << "CONSTRUCT" << endl;
	}
	//拷贝构造函数
	Student(const Student& stu)//加引用
	{
		size = stu.size;
		name = new char[size];
		for (int i = 0; i < size; i++)
		{
			name[i] = stu.name[i];
		}
		cout << "COPY CONSTRUCT" << endl;
	}

	//浅拷贝,
	//和拷贝的对象一模一样,指向了同一片内存
	//指针悬挂
	//移动构造函数
	Student(Student&& stu)
	{
		size = stu.size;
		name = stu.name;
		stu.name = nullptr;
		cout << "MOVE CONSTRUCT" << endl;
	}
	
	~Student()
	{
		delete[] name;
		cout << "DELETE" << endl;
	}
};
Student create()
{
	return Student(5);
}
int main()
{
	vector school;
	//std::move()将一个左值转换成右值
	Student stu(5);//他是一个左值
	school.push_back(std::move(stu));
	//cout << "---------------" << endl;
	//school.push_back(create());
	//cout << "school的堆" << sizeof(school) << endl;
}

STL手撕_第4张图片

右值引用就是把右值变成左值,通常实在C++返回值上,对于自定子类的重复拷贝做了重要改善,大大提高了C++的效率。

type traits

一、 c++ traits

    traits是c++模板编程中使用的一种技术,主要功能: 
    把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用traits提取的属性,使得函数对不同的参数表现一致。

    traits是一种特性萃取技术,它在Generic Programming中被广泛运用,常常被用于使不同的类型可以用于相同的操作,或者针对不同类型提供不同的实现.traits在实现过程中往往需要用到以下三种C++的基本特性: 
enum、typedef、template (partial) specialization 
其中: 
    enum用于将在不同类型间变化的标示统一成一个,它在C++中常常被用于在类中替代define,你可以称enum为类中的define; 
    typedef则用于定义你的模板类支持特性的形式,你的模板类必须以某种形式支持某一特性,否则类型萃取器traits将无法正常工作 
    template (partial) specialization被用于提供针对特定类型的正确的或更合适的版本.

你可能感兴趣的:(#,STL,c++,算法,开发语言)