C++自学精简教程 目录(必读)
这里的版本主要是使用模板实现、支持随机访问迭代器,支持std::sort等所有STL算法。(本文对随机迭代器的支持参考了 复旦大学 大一公共基础课C++语言的一次作业)
随机访问迭代器的实现主要是继承std::iterator
随机访问迭代器最牛逼的两个接口是:
friend iterator operator+(const iterator& lhs, size_t n);
friend iterator operator-(const iterator& lhs, size_t n);
1 为何下面代码中的iterator是struct而不是class?
答:参考struct与class
头文件 Vector.h :
#ifndef VEC_H
#define VEC_H
#include
#include
#include
//------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
#include
#include
#include
#include
#include
using namespace std;
struct Record { Record(void* ptr1, size_t count1, const char* location1, int line1, bool is) :ptr(ptr1), count(count1), line(line1), is_array(is) { int i = 0; while ((location[i] = location1[i]) && i < 100) { ++i; } }void* ptr; size_t count; char location[100] = { 0 }; int line; bool is_array = false; bool not_use_right_delete = false; }; bool operator==(const Record& lhs, const Record& rhs) { return lhs.ptr == rhs.ptr; }std::vector myAllocStatistic; void* newFunctionImpl(std::size_t sz, char const* file, int line, bool is) { void* ptr = std::malloc(sz); myAllocStatistic.push_back({ ptr,sz, file, line , is }); return ptr; }void* operator new(std::size_t sz, char const* file, int line) { return newFunctionImpl(sz, file, line, false); }void* operator new [](std::size_t sz, char const* file, int line)
{
return newFunctionImpl(sz, file, line, true);
}void operator delete(void* ptr) noexcept { Record item{ ptr, 0, "", 0, false }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }void operator delete[](void* ptr) noexcept { Record item{ ptr, 0, "", 0, true }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (!itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }
#define new new(__FILE__, __LINE__)
struct MyStruct { void ReportMemoryLeak() { std::cout << "Memory leak report: " << std::endl; bool leak = false; for (auto& i : myAllocStatistic) { if (i.count != 0) { leak = true; std::cout << "leak count " << i.count << " Byte" << ", file " << i.location << ", line " << i.line; if (i.not_use_right_delete) { cout << ", not use right delete. "; } cout << std::endl; } }if (!leak) { cout << "No memory leak." << endl; } }~MyStruct() { ReportMemoryLeak(); } }; static MyStruct my; void check_do(bool b, int line = __LINE__) { if (b) { cout << "line:" << line << " Pass" << endl; } else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); } }
#define check(msg) check_do(msg, __LINE__);
//------上面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
template
class Vector
{
public:
/* 提供默认构造函数, 否则只能使用有参版本,这会带来不变
例如,Vector arr; 这样会报错,因为需要默认构造函数
*/
Vector(void);//如果类提供了非默认构造函数,编译器不会自动提供默认构造函数
Vector(const Vector& from);// 复制构造函数
Vector(T* start, T* end);// 非默认构造函数
Vector(int count, int value);//2 非默认构造函数
Vector(std::initializer_list value_array)
{
for (auto& item : value_array)
{
push_back(item);
}
}
Vector& operator = (const Vector& from);
bool operator==(const Vector& other) const
{
//(1) your code
return false;
}
//赋值操作符
~Vector();//析构函数
public:
size_t size(void) const;
bool empty(void) const;
T& operator[] (size_t n) const;
T& operator[] (size_t n);
void push_back(const T& val);
void clear(void);
private:
void deep_copy_from(const Vector& from);
public:
struct iterator : std::iterator
{
friend class Vector;
friend bool operator == (const iterator& lhs, const iterator& rhs) { return lhs.m_hold == rhs.m_hold; }
friend bool operator != (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); }
friend size_t operator - (const iterator& lhs, const iterator& rhs) { return lhs.m_hold - rhs.m_hold; }
friend bool operator < (const iterator& lhs, const iterator& rhs) { return lhs.m_hold < rhs.m_hold; }
friend bool operator > (const iterator& lhs, const iterator& rhs) { return lhs.m_hold > rhs.m_hold; }
friend bool operator <= (const iterator& lhs, const iterator& rhs) { return !(lhs > rhs); }
friend bool operator >= (const iterator& lhs, const iterator& rhs) { return !(lhs < rhs); }
friend iterator operator + (const iterator& lhs, size_t n) { iterator itr; itr.m_hold = lhs.m_hold + n; return itr; }//随机访问迭代器牛逼的地方
friend iterator operator - (const iterator& lhs, size_t n) { iterator itr; itr.m_hold = lhs.m_hold - n; return itr; }//随机访问迭代器牛逼的地方
public:
//用于前置形式
iterator& operator++() { m_hold = m_hold + 1; return *this; };
iterator& operator--() { m_hold = m_hold - 1; return *this; };
//用于后置形式
iterator operator++(int) { iterator itr = *this; m_hold += 1; return itr; }
iterator operator--(int) { iterator itr = *this; m_hold -= 1; return itr; }
T& operator*() const//这里必须是const in C++14
{
return *m_hold;
}
private:
T* m_hold;
};
struct const_iterator : std::iterator
{
friend class Vector;
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold == rhs.m_hold; }
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs == rhs); }
friend size_t operator - (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold - rhs.m_hold; }
friend bool operator < (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold < rhs.m_hold; }
friend bool operator > (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold > rhs.m_hold; }
friend bool operator <= (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs > rhs); }
friend bool operator >= (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs < rhs); }
friend const_iterator operator + (const const_iterator& lhs, size_t n) { const_iterator itr; itr.m_hold = lhs.m_hold + n; return itr; }//随机访问迭代器牛逼的地方
friend const_iterator operator - (const const_iterator& lhs, size_t n) { const_iterator itr; itr.m_hold = lhs.m_hold - n; return itr; }//随机访问迭代器牛逼的地方
public:
//用于前置形式
const_iterator& operator++() { m_hold = m_hold + 1; return *this; };
const_iterator& operator--() { m_hold = m_hold - 1; return *this; };
//用于后置形式
const_iterator operator++(int) { const_iterator itr = *this; m_hold += 1; return itr; }
const_iterator operator--(int) { const_iterator itr = *this; m_hold -= 1; return itr; }
const T& operator*() const
{
return *m_hold;
}
private:
T* m_hold;
};
iterator begin() noexcept
{
iterator itr;
itr.m_hold = empty() ? nullptr : &m_data[0];
return itr;
}
const_iterator cbegin() const noexcept;
iterator end() noexcept
{
iterator itr;
itr.m_hold = empty() ? nullptr : &m_data[m_size];
return itr;
}
const_iterator cend() const noexcept;
private:
size_t m_size = 0;//当前元素数量
size_t m_capacity = 0;//容量
T* m_data = nullptr;//数据部分
};
template
Vector::Vector(void)
{
}
template
Vector::Vector(T * start, T * end)
{
std::cout << "Vector(T* start, T* end)" << std::endl;
assert(start != nullptr && end != nullptr);
m_capacity = m_size = ((size_t)end - (size_t)start)/sizeof(T);//这里如果用int来存放可能会盛不下,size_t可以保证盛放的下
assert(m_size > 0);
m_data = new T[m_size];
for (size_t i = 0; i < m_size; i++)
{
m_data[i] = *start++;
}
}
template
Vector::Vector(int count, int value)
{
std::cout << "Vector(count, value)" << std::endl;
if (count <= 0)
{
throw std::runtime_error("size of vector to init must bigger than zero!");
}
m_data = new T[count];
for (size_t i = 0; i < count; i++)
{
m_data[i] = value;
}
m_capacity = m_size = count;
}
template
Vector& Vector::operator=(const Vector& from)
{
std::cout << "Vector::operator=" << std::endl;
if (this == &from)
{
return *this;
}
//先释放自己的数据
clear();
deep_copy_from(from);
return *this;
}
template
Vector::~Vector()
{
//(2) your code
}
template
size_t Vector::size(void) const
{
return m_size;
}
template
bool Vector::empty(void) const
{
//(3) your code
return false;//此处需要修改。
}
template
T& Vector::operator[](size_t n) const
{
//(4) your code
static T t;//此处需要修改。
return t;//此处需要修改。
}
template
T& Vector::operator[](size_t n)
{
//(4) your code
static T t;//此处需要修改。
return t;//此处需要修改。
}
template
void Vector::push_back(const T & val)
{
//(5) your code
// 这里需要考虑第一次插入数据的时候还没有开辟任何动态空间的情况,因为构造函数不再负责事先开辟好少量的初始预留空间了
}
template
void Vector::clear(void)
{
//(6) your code
}
template
void Vector::deep_copy_from(const Vector& from)
{
//(7) your code
}
template
Vector::Vector(const Vector& from)
{
//(8) your code
}
template
typename Vector::const_iterator Vector::cend() const noexcept
{
Vector::const_iterator itr;
//(9) your code
return itr;
}
template
typename Vector::const_iterator Vector::cbegin() const noexcept
{
const_iterator itr;
//(10) your code
return itr;
}
#endif
测试代码main.cpp:
#include
#include
#include "Vector.h"
#include
template
void print(const Vector& v, const std::string& msg)
{
std::cout << "The contents of " << msg.c_str() << " are:";
for (int i = 0; i < v.size(); ++i)
{
std::cout << ' ' << v[i];
}
std::cout << '\n';
}
template
void print_itr(Vector& v, const std::string& msg)
{
std::cout << "The contents of " << msg.c_str() << " are:";
for (auto itr = v.begin(); itr != v.end(); ++itr)
{
std::cout << ' ' << *itr;
}
std::cout << '\n';
}
template
void print_const_itr(const Vector& v, const std::string& msg)
{
std::cout << "The contents of " << msg.c_str() << " are:";
for (auto itr = v.cbegin(); itr != v.cend(); ++itr)
{
std::cout << ' ' << *itr;
}
std::cout << '\n';
}
int main()
{
Vector a;
Vector first; // empty vector of ints
check(first.empty() == true && first.size() == 0);
Vector second(4, 100); // four ints with value 100
check(second.empty() == false);
check(second.size() == 4);
check(*second.begin() == 100);
Vector fourth(second); // a copy of third
check(fourth.size() == second.size());
int myints[] = { 16,2,77,29 };
Vector fifth(myints, myints + sizeof(myints) / sizeof(int));
check(fifth.empty() == false);
check(fifth[0] == 16);
check(fifth[3] == 29);
check(fifth.size() == sizeof(myints) / sizeof(int));
print(fifth, "fifth");//The contents of fifth are:16 2 77 29
fifth.push_back(30);
check(fifth[4] == 30);
check(fifth.size() == 5);
print(fifth, "fifth");//The contents of fifth are:16 2 77 29 30
check(fifth.size() == sizeof(myints) / sizeof(int) + 1);
first = fifth = fifth;
print(first, "first");//The contents of first are:16 2 77 29 30
check(first.empty() == false && first.size() == fifth.size());
print_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30
print_const_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30
std::sort(fifth.begin(), fifth.end());
std::cout << "fifith after sort:" << std::endl;
print_const_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30
Vector a1(myints, myints + sizeof(myints) / sizeof(int));
{
Vector b(a1);
b.push_back(2);
check(b[4] == 2);
auto result = (b == Vector{ 16, 2, 77, 29, 2});
check(result);
//iterator
check(b.begin() + b.size() == b.end());
auto begin = b.begin();
auto itr = b.begin() + 1;
check(*begin == 16);
check(*itr == 2);
}
{
Vector b{ 1,3,5,7 };
b.push_back(9);
}
{
Vector c;
for (auto i : c)
{
std::cout << i << " ";
}
c = a1;
for (auto i : c)
{
std::cout << i << " ";
}
std::cout << std::endl;
}
check(a1.size() == sizeof(myints) / sizeof(int));
{
Vector c;
c = fifth;
c[0] = 1;
check(c[0] == 1);
}
}
line:42 Pass
Vector(count, value)
line:44 Pass
line:45 Pass
line:46 Pass
line:48 Pass
Vector(T* start, T* end)
line:52 Pass
line:53 Pass
line:54 Pass
line:55 Pass
The contents of fifth are: 16 2 77 29
line:58 Pass
line:59 Pass
The contents of fifth are: 16 2 77 29 30
line:61 Pass
Vector::operator=
Vector::operator=
The contents of first are: 16 2 77 29 30
line:64 Pass
The contents of fifth are: 16 2 77 29 30
The contents of fifth are: 16 2 77 29 30
fifith after sort:
The contents of fifth are: 2 16 29 30 77
Vector(T* start, T* end)
line:74 Pass
line:76 Pass
Vector::operator=
16 2 77 29
line:95 Pass
Vector::operator=
line:100 Pass
Memory leak report:
No memory leak.
Vector<T> 动态数组(随机访问迭代器)(答案)_C++开发者的博客-CSDN博客