简易vector:
vector的操作:
push_back(), pop_back(),
单端的容器
实现一个简易的vector:
#include<iostream>
using namespace std;
template<typename T>
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<typename T>
ostream& operator<<(ostream& cout, MyVector<T> vec)
{
for (int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
return cout;
}
int main()
{
MyVector<int> vec(10);
for (int i = 0; i < vec.size(); i++)
{
vec.push_back(i);
}
for (MyVector<int>::iterator it = vec.begin(); it != vec.end(); it++)
{
cout << *it << " ";
}
}
什么是右值引用?移动语义源码剖析
什么是左值和右值?
按照我们常规理解左值就是在等号左边的值,右值是等号右边的值。如果你要这么理解,你就会发现遇到++i
或i++
这一类的语句你就开始混乱了!
其实左值和右值是我们习惯性的叫法,他的全拼应该是:
左值是:locator value
(可寻址的数据)
右值是:read value
(不可寻址的数据或用来读的数据)
左值、右值、左值引用和右值引用_左值右值_四库全书的酷的博客-CSDN博客
举例说明:
右值:x++
//x++;这个从底层去分析:
//x++会产生一个临时变量,用来保存x+1的值,
//等到语句结束,将x+1赋值给x.
//但是语句没结束时,这个临时变量时在寄存器中保存的,一个计算结果的临时变量,
//此时是不可寻址的!!即右值。x=x+1
左值:++x
//这里面++x是直接对x自增,我们得到的值就是x的值,
左值引用
1 左值引用得到的就是还是一个左值。
2 左值引用,它的本质就是指针常量
3 左值引用就是一个不能变的指针,所以在定义引用的时候就需要给它初始化,因为他之后就不可以改变了。
非常量引用的初始值必须为左值,很明显5不是左值,没有地址可以寻找
右值引用 (important!!!)
右值引用的使用常常在自定义类中,可以查看该博文去理解。
右值引用操作符为 “&&”;
右值引用得到的是一个左值。
右值引用通常将一个临时变量拿过来用。
右值引用最主要的功能是解决的是自定义类重复构造冗余的问题。#include<iostream> #include<vector> 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<Student> school; //std::move()将一个左值转换成右值 Student stu(5);//他是一个左值 school.push_back(std::move(stu)); //cout << "---------------" << endl; //school.push_back(create()); //cout << "school的堆" << sizeof(school) << endl; }
右值引用就是把右值变成左值,通常实在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被用于提供针对特定类型的正确的或更合适的版本.