一、学习复数类CComplex
C++运算符重载:使对象的运算表现得和编译器内置类型一样。
注意:编译器做对象运算的时候,会调用对象的运算符重载函数(优先调用成员方法),如果没有成员方法,就在全局作用域找合适的运算符重载函数
代码:
#include<iostream>
using namespace std;
class CComplex
{
public:
CComplex(int r = 0,int i=0)
:mreal(r),mimage(i){}
CComplex operator+(const CComplex& src)
{
return CComplex(mreal + src.mreal, mimage + src.mimage);
}
CComplex operator++()
{
return CComplex(++mreal, ++mimage);
}
CComplex operator++(int)
{
mreal += 1;
mimage += 1;
return *this;
}
void operator+=(const CComplex& src)
{
mreal += src.mreal;
mimage += src.mimage;
}
void show()
{
cout << "mreal:" << mreal << " mimage:" << mimage << endl;
}
private:
int mreal;
int mimage;
friend CComplex operator+(const CComplex& lhs, const CComplex& rhs);
friend ostream& operator<<(ostream& out, const CComplex& src);
friend istream& operator>>(istream& in, CComplex& src);
};
CComplex operator+(const CComplex& lhs, const CComplex& rhs)
{
return CComplex(lhs.mreal + rhs.mreal, lhs.mimage + rhs.mimage);
}
ostream& operator<<(ostream& out, const CComplex& src)
{
out << "mreal:" << src.mreal << " mimage:" << src.mimage << endl;
return out;
}
istream& operator>>(istream& in, CComplex& src)
{
in >> src.mreal >> src.mimage;
return in;
}
int main()
{
CComplex comp1(10, 10);
CComplex comp2(20, 20);
CComplex comp3 = comp1 + comp2;
comp3.show();
CComplex comp4 = comp1 + 20;
comp4.show();
CComplex comp5 = 30 + comp1;
comp5.show();
cout << "-----------------------------" << endl;
comp5 = comp1++;
comp1.show();
comp5.show();
comp5 = ++comp1;
comp1.show();
comp5.show();
cout << "-----------------------------" << endl;
comp1 += comp2;
comp1.show();
cout << "-----------------------------" << endl;
cin >> comp1 >> comp2;
cout << comp1 << comp2 << endl;
return 0;
}
运行结果:
二、模拟实现C++的string类代码
#include<iostream>
using namespace std;
class String
{
public:
String(const char* p = nullptr)
{
if (p!=nullptr)
{
_pstr = new char[strlen(p) + 1];
strcpy(_pstr, p);
}
else
{
_pstr = new char(1);
*_pstr = '\0';
}
}
String(const String& src)
{
_pstr = new char[strlen(src._pstr) + 1];
strcpy(_pstr, src._pstr);
}
String& operator=(const String& src)
{
if (this == &src)
{
return *this;
}
delete[]_pstr;
_pstr = new char[strlen(src._pstr) + 1];
strcpy(_pstr, src._pstr);
return *this;
}
bool operator>(const String& src)
{
return strcmp(_pstr, src._pstr) > 0;
}
bool operator<(const String& src)
{
return strcmp(_pstr, src._pstr) < 0;
}
bool operator==(const String& src)
{
return strcmp(_pstr, src._pstr) == 0;
}
~String()
{
delete[]_pstr;
_pstr = nullptr;
}
int length() { return strlen(_pstr); }
const char* c_str()const { return _pstr; }
char& operator[](int index) { return _pstr[index]; }
const char& operator[](int index)const { return _pstr[index]; }
private:
char* _pstr;
friend ostream& operator<<(ostream& out, const String& str);
friend String operator+(const String& lhs, const String& rhs);
};
String operator+(const String& lhs, const String& rhs)
{
char* ptmp = new char(strlen(lhs._pstr) + strlen(rhs._pstr) + 1);
strcpy(ptmp, lhs._pstr);
strcat(ptmp, rhs._pstr);
return String(ptmp);
}
ostream& operator<<(ostream& out, const String& str)
{
out << str._pstr;
return out;
}
int main()
{
string str1;
string str2 = "aaa";
string str3 = "bbb";
string str4 = str2 + str3;
string str5 = str2 + "ccc";
string str6 = "ddd" + str2;
cout << "str6:" << str6 << endl;
if (str5 > str6)
{
cout << str5 << ">" << str6 << endl;
}
else
{
cout << str5 << "<" << str6 << endl;
}
int len = str6.length();
for (int i = 0; i < len; i++)
{
cout << str6[i] << " ";
}
cout << endl;
char buf[1024] = { 0 };
strcpy(buf, str6.c_str());
return 0;
}
三、string字符串对象的迭代器iterator的实现
#include<iostream>
using namespace std;
class String
{
public:
String(const char* p = nullptr)
{
if (p!=nullptr)
{
_pstr = new char[strlen(p) + 1];
strcpy(_pstr, p);
}
else
{
_pstr = new char(1);
*_pstr = '\0';
}
}
String(const String& src)
{
_pstr = new char[strlen(src._pstr) + 1];
strcpy(_pstr, src._pstr);
}
String& operator=(const String& src)
{
if (this == &src)
{
return *this;
}
delete[]_pstr;
_pstr = new char[strlen(src._pstr) + 1];
strcpy(_pstr, src._pstr);
return *this;
}
bool operator>(const String& src)const
{
return strcmp(_pstr, src._pstr) > 0;
}
bool operator<(const String& src)const
{
return strcmp(_pstr, src._pstr) < 0;
}
bool operator==(const String& src)const
{
return strcmp(_pstr, src._pstr) == 0;
}
~String()
{
delete[]_pstr;
_pstr = nullptr;
}
int length()const { return strlen(_pstr); }
const char* c_str()const { return _pstr; }
char& operator[](int index) { return _pstr[index]; }
const char& operator[](int index)const { return _pstr[index]; }
class iterator
{
public:
iterator(char *p=nullptr):_p(p){}
bool operator!=(const iterator& it)
{
return _p != it._p;
}
void operator++()
{
++_p;
}
char& operator*() { return *_p; }
private:
char* _p;
};
iterator begin() { return iterator(_pstr); }
iterator end() {return iterator(_pstr + length());}
private:
char* _pstr;
friend ostream& operator<<(ostream& out, const String& str);
friend String operator+(const String& lhs, const String& rhs);
};
String operator+(const String& lhs, const String& rhs)
{
String tmp;
tmp._pstr = new char(strlen(lhs._pstr) + strlen(rhs._pstr) + 1);
strcpy(tmp._pstr, lhs._pstr);
strcat(tmp._pstr, rhs._pstr);
return tmp;
}
ostream& operator<<(ostream& out, const String& str)
{
out << str._pstr;
return out;
}
int main()
{
String str1 = "hello world!";
String::iterator it = str1.begin();
for (; it != str1.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
for (char ch : str1)
{
cout << ch << " ";
}
cout << endl;
#if 0
String str1;
String str2 = "aaa";
String str3 = "bbb";
String str4 = str2 + str3;
String str5 = str2 + "ccc";
String str6 = "ddd" + str2;
cout << "str6:" << str6 << endl;
if (str5 > str6)
{
cout << str5 << ">" << str6 << endl;
}
else
{
cout << str5 << "<" << str6 << endl;
}
int len = str6.length();
for (int i = 0; i < len; i++)
{
cout << str6[i] << " ";
}
cout << endl;
char buf[1024] = { 0 };
strcpy(buf, str6.c_str());
#endif
return 0;
}
四、vector容器的迭代器iterator实现
#include <iostream>
using namespace std;
template<typename T>
class vector
{
public:
vector(int size = 10)
{
_first = new T[size];
_last = _first;
_end = _first + size;
}
~vector()
{
delete[]_first;
_first = _last = _end = nullptr;
}
vector(const vector<T>& rhs)
{
int size = rhs._end - rhs._first;
_first = new T[size];
int len = rhs._last - rhs._first;
for (int i = 0; i < len; i++)
{
_first[i] = rhs._first[i];
}
_last = _first + len;
_end = _first + size;
}
vector<T>& operator=(const vector<T>& rhs)
{
if (this == &rhs)
return*this;
delete[]_first;
int size = rhs._end - rhs._first;
_first = new T[size];
int len = rhs._last - rhs._first;
for (int i = 0; i < len; i++)
{
_first[i] = rhs._first[i];
}
_last = _first + len;
_end = _first + size;
}
void push_back(const T& val)
{
if (full())
expand();
*_last++ = val;
}
void pop_back()
{
if (empty())
return;
_last--;
}
T back()const
{
return *(_last - 1);
}
bool full() { return _last == _end; }
bool empty() { return _last == _first; }
int size() { return _last - _first; }
T& operator[](int index)
{
if (index < 0 || index >= size())
{
throw"OutOfRangeException";
}
return _first[index];
}
class iterator
{
public:
iterator(T*ptr=nullptr)
:_ptr(ptr){}
bool operator!=(const iterator& it)const
{
return _ptr != it._ptr;
}
void operator++()
{
_ptr++;
}
T& operator*() { return *_ptr; }
const T& operator*()const { return *_ptr; }
private:
T* _ptr;
};
iterator begin() { return iterator(_first); }
iterator end() { return iterator(_last); }
private:
T* _first;
T* _last;
T* _end;
void expand()
{
int size = _end - _first;
T* ptmp = new T[size * 2];
for (int i = 0; i < size; i++)
{
ptmp[i] = _first[i];
}
delete[]_first;
_first = ptmp;
_last = _first + size;
_end = _first + size * 2;
}
};
int main()
{
vector<int> vec;
for (int i = 0; i < 20; i++)
{
vec.push_back(rand() % 100 + 1);
}
int size = vec.size();
for (int i = 0; i < size; ++i)
{
cout << vec[i] << " ";
}
cout << endl;
vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
for (int val : vec)
{
cout << val << " ";
}
cout << endl;
return 0;
}
五、容器的迭代器失效问题
1.迭代器为什么会失效?
a:当容器调用erase方法后,当前位置到容器末尾元素的所有迭代器全部失效了
b:当容器调用insert方法后,当前位置到容器末尾元素的所有迭代器全部失效了
c:insert来说,如果引起容器内存扩容,原来容器的所有的迭代器就全部失效了
2.迭代器失效后,问题该怎么解决?
对插入/删除点的迭代器进行更新操作
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> vec;
for (int i = 0; i < 20; ++i)
{
vec.push_back(rand() % 100 + 1);
}
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
#if 1
auto it = vec.begin();
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
it = vec.insert(it, *it - 1);
++it;
}
}
#endif
#if 0
auto it = vec.begin();
while(it != vec.end())
{
if (*it % 2 == 0)
{
it=vec.erase(it);
}
else
{
++it;
}
}
#endif
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
return 0;
}
六、new和delete的原理
1、malloc和new的区别
- malloc按字节开辟内存的;new开辟内存时需要指定类型 new int[10],所以malloc开辟内存返回的是void* operator new->int*
- malloc只负责开辟空间,new不仅仅有malloc的功能,还可以进行数据初始化
- malloc开辟内存失败返回nullptr指针;new抛出的是bad_alloc类型的异常
2、free和delete的区别
delete (int*)p:调用析构函数,再free§
#include<iostream>
using namespace std;
void* operator new(size_t size)
{
void* p = malloc(size);
if (p == nullptr)
throw bad_alloc();
cout << "operator new addr:" << p << endl;
return p;
}
void operator delete(void* ptr)
{
cout << "operator delete addr:" << ptr << endl;
free(ptr);
}
void* operator new[](size_t size)
{
void* p = malloc(size);
if (p == nullptr)
throw bad_alloc();
cout << "operator new[] addr:" << p << endl;
return p;
}
void operator delete[](void* ptr)
{
cout << "operator delete[] addr:" << ptr << endl;
free(ptr);
}
int main()
{
try
{
int* p = new int;
delete p;
int* q = new int[5];
delete[]q;
}
catch (const bad_alloc& err)
{
cerr << err.what() << endl;
}
return 0;
}
3、new和delete能混用吗?C++为什么区分单个元素和数组的内存分配和释放呢?
正常搭配:new/delete;new[]/delete[]
对于普通的编译器内置类型 new/delete[];new[]/delete也可以;
自定义的类类型,有析构函数,为了调用正确的析构函数,那么开辟对象数组的时候,会多开辟4个字节,记录对象的个数。这时候不能混用!
七、new和delete重载实现的对象池应用
#include<iostream>
using namespace std;
template<typename T>
class Queue
{
public:
Queue()
{
_front = _rear = new QueueItem();
}
~Queue()
{
QueueItem* cur = _front;
while (cur != nullptr)
{
_front = _front->_next;
delete cur;
cur = _front;
}
}
void push(const T &val)
{
QueueItem* item = new QueueItem(val);
_rear->_next = item;
_rear = item;
}
void pop()
{
if (empty())
return;
QueueItem* first = _front->_next;
_front->_next = first->_next;
if (_front->_next == nullptr)
{
_rear = _front;
}
delete first;
}
T front()const
{
return _front->_next->_data;
}
bool empty()const { return _front == _rear; }
private:
struct QueueItem
{
QueueItem(T data = T()) :_data(data), _next(nullptr) {};
void* operator new(size_t size)
{
if (_itemPool == nullptr)
{
_itemPool = (QueueItem*)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];
QueueItem* p = _itemPool;
for (; p < _itemPool + POOL_ITEM_SIZE-1; ++p)
{
p->_next = p + 1;
}
p->_next = nullptr;
}
QueueItem* p = _itemPool;
_itemPool = _itemPool->_next;
return p;
}
void operator delete(void* ptr)
{
QueueItem* p = (QueueItem*)ptr;
p->_next = _itemPool;
_itemPool = p;
}
T _data;
QueueItem* _next;
static QueueItem* _itemPool;
static const int POOL_ITEM_SIZE = 100000;
};
QueueItem* _front;
QueueItem* _rear;
};
template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::_itemPool = nullptr;
int main()
{
Queue<int> que;
for (int i = 0; i < 1000000; i++)
{
que.push(i);
que.pop();
}
cout << que.empty() << endl;
return 0;
}
|