十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
編譯器做對象運算的時候,會調(diào)用對象的運算符重載函數(shù)(優(yōu)先調(diào)用成員方法);如果沒有成員方法,就砸全局作用域找合適的運算符重載函數(shù)

十余年的東蘭網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整東蘭建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“東蘭網(wǎng)站設(shè)計”,“東蘭網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
++和--運算符是單目運算符,在參數(shù)列表里放上一個int表示其在數(shù)的前面還是后面:operator++()表示前置,operator++(int)表示后置,括號里的int沒有任何作用。
復(fù)數(shù)類的具體實現(xiàn):
//
// Created by on 2022-05-16 13:43.
// Description:CComplex.h
//
#ifndef C___CCOMPLEX_H
#define C___CCOMPLEX_H
#include
using namespace std;
class CComplex {
friend CComplex operator+(const CComplex &l, const CComplex &r);
friend iostream &operator<<(ostream &os, const CComplex &src);
friend istream & operator>>(istream& is, CComplex &src);
public:
explicit CComplex(int r = 0, int i = 0) : _real(r), _image(i) {}
// CComplex operator+(const CComplex& src) const{
// return CComplex(this->_real+src._real,this->_image+src._image);
// }
void show() {
cout << "real: " << _real << " image: " << _image << endl;
}
CComplex &operator++() {
++_real;
++_image;
return *this;
}
CComplex operator++(int) {
return CComplex(_real++, _image++);
}
private:
int _real;
int _image;
};
inline CComplex operator+(const CComplex &l, const CComplex &r) {
return CComplex(l._real + r._real, l._image + r._image);
}
inline iostream &operator<<(ostream &os, const CComplex &src) {//重載輸出操作
os << "real: " << src._real << " image: " << src._image << endl;
}
inline istream & operator>>(istream& is,CComplex &src){//重載輸入操作
is>>src._real>>src._image;
}
#endif //C___CCOMPLEX_H
主函數(shù):
int main(){
CComplex cp1(10,15);
CComplex cp2(20,30);
CComplex cp3=cp2+cp1;
cp3.show();
CComplex cp4=cp3++;
cp4.show();
cp3.show();
CComplex cp5= ++cp3;
cp5.show();
cp3.show();
cout<>cp6;
cout<
//
// Created by on 2022-05-16 14:30.
// Description:String.h
//
#ifndef C___STRING_H
#define C___STRING_H
#include
#include
class String {
friend std::ostream &operator<<(std::ostream &os, const String &src);
public:
String(const char *src = nullptr) {
if (src == nullptr) {
_pstr = new char[1];
*_pstr = '\0';
} else {
_pstr = new char[strlen(src) + 1];
strcpy(_pstr, src);
}
}
~String() {
delete[] _pstr;
_pstr = nullptr;
}
String(const String &src) {
_pstr = new char[strlen(src._pstr) + 1];
strcpy(_pstr, src._pstr);
}
bool operator>(const String &str) const {
return strcmp(_pstr, str._pstr) > 0;
}
bool operator<(const String &str) const {
return strcmp(_pstr, str._pstr) < 0;
}
bool operator==(const String &str) const {
return strcmp(_pstr, str._pstr) == 0;
}
int length() const {
return strlen(_pstr);
}
char &operator[](int index) {
return _pstr[index];
}
char *c_str() const {
return _pstr;
}
private:
char *_pstr;
};
inline std::ostream &operator<<(std::ostream &os, const String &src) {
os << src._pstr;
return os;
}
inline String operator+(const String& l,const String& r){
char* ptmp=new char[strlen(l.c_str())+ strlen(r.c_str())+1];
strcpy(ptmp,l.c_str());
strcat(ptmp,r.c_str());
String temp(ptmp);
delete[] ptmp;
return temp;
}
#endif //C___STRING_H
目前代碼中的加法的重載運算效率不高,需要進一步改進。
上面代碼的加法重載函數(shù),會生成臨時對象,影響性能。
暫時改進為:
inline String operator+(const String &l, const String &r) {
// char *ptmp = new char[strlen(l.c_str()) + strlen(r.c_str()) + 1];
String temp;
temp._pstr=new char[strlen(l.c_str()) + strlen(r.c_str()) + 1];//避免了開辟兩次內(nèi)存空間
strcpy(temp._pstr, l.c_str());
strcat(temp._pstr, r.c_str());
// String temp(ptmp);
// delete[] ptmp;
return temp;
}
迭代器可以透明的訪問容器內(nèi)部元素的值
foreach遍歷容器,其底層是用迭代器實現(xiàn)的
迭代器的功能:提供一種統(tǒng)一的方式,透明的遍歷容器
在對迭代器加加時,一般用前置的++,因為不會生成新的對象,效率會高一些
/**
* 迭代器的實現(xiàn), 放在String類中
*/
class Iterator{
public:
Iterator(char* p= nullptr):_p(p){}
bool operator!=(const String::Iterator&it){//判斷兩個迭代器是否相等
return _p!=it._p;
}
void operator++(){
++ _p;
}
char& operator*(){return *_p;}
private:
char* _p;
};
Iterator begin(){
return {_pstr};
}
Iterator end(){
return {_pstr+length()};
}
迭代器一般實現(xiàn)成容器的嵌套結(jié)構(gòu)。
在VectorT類中添加以下代碼:
class iterator {
public:
iterator(const T *p = nullptr)
: _ptr((int *) p) {}
bool operator!=(const VectorT::iterator &it) {
return _ptr != it._ptr;
}
void operator++() {
++_ptr;
}
T &operator*() { return *_ptr; }
private:
T *_ptr;
};
iterator begin(){
return {_first};
}
iterator end(){
return {_last};
}
1、調(diào)用erase后,當前位置到末尾元素的迭代器就會失效。
2、調(diào)用insert后,當前位置到末尾元素的迭代器就會失效
3、容器擴容后迭代器也會失效
首元素到插入點/刪除點的迭代器依然有效
迭代器失效該怎么解決?要對迭代器進行更新操作!
不同容器的迭代器是不能進行比較運算的
vector中迭代器的實現(xiàn)(包含迭代器失效的判斷)
//
// Created by on 2022-05-15 20:33.
// Description:
//
#ifndef C___VECTORT_H
#define C___VECTORT_H
#include "AllocatorT.h"
using namespace std;
/**
* 容器底層內(nèi)存開辟,內(nèi)存釋放,對象構(gòu)造和析構(gòu)都通過allocator實現(xiàn)
* @tparam T
* @tparam Alloc
*/
template >
class VectorT {
public:
VectorT(int size = 10) {
// _first=new T[size];
_first = _alloctor.allocate(size);
_last = _first;
_end = _first + size;
}
~VectorT() {
// delete[] _first;
//使用allocator對vector逐個刪除
for (T *p = _first; p != _last; ++p) {
_alloctor.destory(p);
}
_alloctor.deallocate(_first);
_first = _last = _end = nullptr;
}
VectorT(const VectorT &src) {
int size = src._end - src._first;
// _first = new T[size];
_first = _alloctor.allocate(size);
int len = src._last - src._first;
for (int i = 0; i < len; i++) {
// _first[i] = src._first[i];
_alloctor.contruct(_first + 1, src._first[i]);
}
_last = _first + len;
_end = _first + size;
}
VectorT &operator=(const VectorT &src) {
if (src == *this) {
return *this;
}
//delete[] _first;
for (T *p = _first; p != _last; p++) {
_alloctor.destory(p);
}
_alloctor.deallocate(_first);
int size = src._end - src._first;
_first = new T[size];
int len = src._last - src._first;
for (int i = 0; i < len; i++) {
// _first[i] = src._first[i];
_alloctor.contruct(_first + 1, src._first[i]);
}
_last = _first + len;
_end = _first + size;
return *this;
}
T &operator[](int index) {
if (index < 0 || index >= size()) {
throw "OutOfRangeException";
}
return _first[index];
}
void push_back(T val) {
if (full()) {
expend();
}
//*_last++ = val;
_alloctor.construct(_last, val);
_last++;
}
void pop_back() {
if (empty()) { return; }
verify(_last - 1, _last);
--_last;
_alloctor.destory(_last);
}
T back() const {
return *(_last - 1);
}
bool full() const {
return _last == _end;
}
bool empty() const {
return _first == _last;
}
int size() const {
return _last - _first;
}
/**
* 實現(xiàn)迭代器
*/
class iterator {
friend void VectorT::verify(T *first, T *last);
friend iterator VectorT::insert(iterator it,const T& val);
friend iterator VectorT::erase(iterator it);
public:
/*iterator(const T *p = nullptr)
: _ptr((int *) p) {}*/
/**
* 根據(jù)新的成員變量實現(xiàn)新的構(gòu)造函數(shù),使其能實現(xiàn)迭代器失效
* @param pvec 容器指針
* @param ptr 位置指針
*/
iterator(VectorT *pvec = nullptr, T *ptr = nullptr) : _ptr(ptr), _pVec(pvec) {
Iterator_Base *itb = new Iterator_Base(this, _pVec->_head._next);//構(gòu)造新節(jié)點
_pVec->_head._next = itb;//將頭結(jié)點連接新節(jié)點
}//接下來就是在改變數(shù)組的過程中使迭代器失效
bool operator!=(const VectorT::iterator &it) {
/**
* 判斷迭代器是否失效
*/
if (_pVec == nullptr || _pVec != it._pVec) {
throw "iterator incompatable!";
}
return _ptr != it._ptr;
}
void operator++() {
if (_pVec == nullptr) {
throw "iterator invalid!";
}
++_ptr;
}
T &operator*() {
if (_pVec == nullptr) {
throw "iterator invalid!";
}
return *_ptr;
}
private:
T *_ptr;
/**
* 實現(xiàn)迭代器失效,首先要添加一個指向容器的指針
*/
VectorT *_pVec;
};
/**
* 根據(jù)新的成員方法生成相應(yīng)的begin和end方法
* @return
*/
iterator begin() {
return {this, _first};
}
iterator end() {
return {this, _last};
}
/**
* 最后一步:判斷迭代器是否失效
* @param first
* @param last
*/
void verify(T *first, T *last) {
Iterator_Base *pre = &this->_head;
Iterator_Base *it = this->_head._next;
while (it != nullptr) {
if (it->_cur->_ptr > first && it->_cur->_ptr <= last) {
//迭代器失效,把iterator持有的容器指針置null
it->_cur->_pVec = nullptr;
//刪除當前迭代器節(jié)點,繼續(xù)判斷后面的迭代器節(jié)點是否失效
pre->_next = it->_next;
delete it;
it = pre->_next;
}else{
pre=it;
it=it->_next;
}
}
}
/**
* 插入操作
* @param it 迭代器位置
* @param val 插入的值
* @return 迭代器
*/
iterator insert(iterator it,const T& val){
/*
* 不考慮擴容,
* 不考慮指針的合法性
*/
verify(it._ptr-1,_last);
T* p=_last;
while(p>it._ptr){
_alloctor.construct(p,*(p-1));
_alloctor.destory(p-1);
p--;
}
_alloctor.construct(p,val);
_last++;
return {this,p};
}
iterator erase(iterator it){
verify(it._ptr-1,_last);
T* p=it._ptr;
while(p<_last-1){//元素向前移
_alloctor.destory(p);
_alloctor.construct(p,*(p+1));
p++;
}
_alloctor.destory(p);
_last--;
return {this,it._ptr-1};
}
private:
T *_first;//表示vector起始位置
T *_last;//表示vector定義元素的末尾
T *_end;//表示vector的末尾
Alloc _alloctor;//負責內(nèi)存管理
/**
* 在鏈表的結(jié)構(gòu)中保存每個迭代器
*/
struct Iterator_Base {
Iterator_Base(iterator *c = nullptr, VectorT::Iterator_Base *n = nullptr) : _cur(c), _next(n) {}
iterator *_cur;
Iterator_Base *_next;
};
/**
* 頭結(jié)點
*/
Iterator_Base _head;
void expend() {//size擴大兩倍
int size = _end - _first;
// T *ptmp = new T[size * 2];
T *ptmp = _alloctor.allocate(2 * size);
for (int i = 0; i < size; i++) {
//ptmp[i] = _first[i];
_alloctor.construct(ptmp + i, _first[i]);
}
//delete[] _first;
for (T *p = _first; p != _last; p++) {
_alloctor.destory(p);
}
_alloctor.deallocate(_first);
_first = ptmp;
_last = _first + size;
_end = _first + (2 * size);
}
};
#endif //C___VECTORT_H
1、malloc和new的區(qū)別:
new int[10],所以malloc開辟內(nèi)存返回的都是void*2、free和delete的區(qū)別:
檢查內(nèi)存泄漏要重寫new和delete
new和delete能混用嗎?C++為什么要區(qū)分單個元素和數(shù)組的內(nèi)存分配和釋放呢?
對于內(nèi)置類型int等,可以混用。但是對于自定義的類,就不能混用,因為自定義的類類型有析構(gòu)函數(shù),為了正確的析構(gòu)函數(shù),在開辟對象數(shù)組的時候會在數(shù)組前多開辟4個字節(jié),記錄對象的個數(shù)。
//兩個操作符的重載
void* operator new(size_t size){
void* p=malloc(size);
if(p== nullptr){
throw bad_alloc();
}
cout<<"opeartor new addr:"<
對象池是在堆上開辟的靜態(tài)鏈表
//
// Created by on 2022-05-17 9:40.
// Description:
//
#ifndef C___QUEUEWITHITEMPOOL_H
#define C___QUEUEWITHITEMPOOL_H
#include
using namespace std;
template
class Queue {
public:
Queue(){//默認構(gòu)造
_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;//尾部元素置為新值,與front區(qū)分開
}
void pop(){
if(empty()){
return;
}
QueueItem* first=_front->_next;
_front->_next=first->_next;
if(_front->_next== nullptr){//如果隊列只有一個有效節(jié)點
_rear=_front;
}
delete first;
}
bool empty() const{
return _front==_rear;
}
T front()const {
return _front->_next->_data;
}
private:
/**
* 實現(xiàn)一個鏈式的隊列,帶有頭結(jié)點
*/
struct QueueItem {
QueueItem(T data=T()):_data(data),_next(nullptr){}
//重載new實現(xiàn)對象池
void* operator new (size_t size){
if(_itemPool== nullptr){//如果未開辟空間;如果當前內(nèi)存池使用完,最后一個元素指向的也是nullptr,會分配新的內(nèi)存池
_itemPool=(QueueItem*)new char[POOL_ITEM_SIZE*sizeof(QueueItem)];//開辟對象池
//我們用char,按字節(jié)開辟,因為如果用new QueueItem,
//就又會調(diào)用到當前這個方法了,
//我們現(xiàn)在就是在給QueueItem自定義new運算符重載
QueueItem* p=_itemPool;
for(;p<_itemPool+POOL_ITEM_SIZE-1;++p){
p->_next=p+1;//初始化連續(xù)鏈表
}
p->_next= nullptr;
}
//新建queueItem的時候會使用對象池中未使用的節(jié)點,然后指向下一個未使用的節(jié)點
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 const int POOL_ITEM_SIZE=;
static QueueItem *_itemPool;
};
QueueItem* _front;//指向頭結(jié)點
QueueItem* _rear;//指向隊尾,
};
template
typename Queue::QueueItem* Queue::QueueItem::_itemPool= nullptr;
#endif //C___QUEUEWITHITEMPOOL_H