首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从零开始学C++之重载 operator new 和 operator delete 实现一个简单内存泄漏跟踪器

先来说下实现思路:可以实现一个Trace类,调用 operator new 的时候就将指向分配内存的指针、当前文件、当前行等信息添加进Trace 成员map容器内,在调用operator delete... new(size_t size, const char *file, long line); void operator delete(void *p); void *operator new[](...分别重载了 operator new 和 operator new[]  函数以及对应的delete,更详细的讨论可以参见这里。...当全局对象NewTrace 析构时调用Dump成员 函数,如果new 和 delete 没有匹配,那么map将存在泄漏信息,并打印出来。...#endif 而由于一般的C++库中可能没有#define new new(__FILE__, __LINE__);  即调用的还是原始的new,但现在程序中并没有重载这种类 型的new

86600

string类(下)(模拟实现string类,深度剖析其底层)

释放空间使用的是delete[]而不是delete,前者是基于new调用的次数来调用多少次,而后者固定只调用一次。...这种写法是错误的,它会导致无穷递归,因为swap函数内部也在进行赋值运算,每次赋值都会调用swap函数,而每次swap也都会进行赋值 7....重载下标索引[] 重载下标索引[ ],在string中的索引比迭代器更加方便 char& operator[](size_t pos) { // 检查pos的合法性,设置断言 assert(pos..._capacity); // // std::swap(tmp, *this); // // 这种写法是错误的,它会导致无穷递归,因为swap函数内部也在进行赋值运算,每次赋值都会调用swap...[],在string中的索引比迭代器更加方便 char& operator[](size_t pos) { // 检查pos的合法性,设置断言 assert(pos < _size)

9510
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【C++】操作符重载的应用—— 重现

    < _year << "-" << _month << "-" << _day << endl; } Date(const Date& d) // 错误写法:(不加引用)编译报错,会引发无穷递归...<=等】 1.代码展示: 类内声明: PS:加const,可以让普通变量和const变量都能调用该函数(具体知识点可见YY的C++知识合集博客,关于const的解读) bool operator...(*this == x); } 三.基本运算符重载【+,+=,-,-=】(日期与天数的运算) 1.代码展示: 类内声明: PS:加const,可以让普通变量和const变量都能调用该函数(具体知识点可见...增加参数int,构成函数重载 2.代码展示: 类内声明: //增加这个int参数不是为了接收具体的值,仅仅是占位,跟前置++构成重载 Date& operator++(); Date operator...减法的重载(日期-日期) 技巧: 预设大小:得以计算绝对值 预设flag:得以实现最终结果 .c文件实现: int Date::operator-(const Date& d) const {

    10610

    类和对象竟是这样的(中集)

    构造函数:构造函数是一个特殊的成员函数,它的函数名和类名相同,创建类类型对象时由编译器调用来初始化成员变量的函数,并且在成员周期内只调用一次。 2.特性 注意注意!...特征: (1)函数名与类名相同 (2)无返回值 (3)类对象实例化时编译器自动调用对应的构造函数 (4)构造函数可以重载 (5)如果用户没有显示声明构造函数,则C嘎嘎编译器会自动生成一个无参的默认构造函数...这是由于对于拷贝构造函数的参数来说相当于又创建了个新的Date类对象,而这个对象无可避免的要去调用他的拷贝构造函数,用d1来拷贝构造date参数,由此无穷递归下去......函数基本构造:返回值+operator+要重载的运算符(参数列表) 注意注意!!!...(1)不能通过函数重载来创建新的操作符,例如:operator@ (2)运算符重载函数必须有一个参数为类类型 (3)对于内置类型的运算符来说,不能通过运算符重载改变它的值,例如:+ (4)实际看起来作为成员函数的运算符重载函数的参数要比设想时少一个

    6910

    类与对象(中(2))

    拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。...这就能很好解释为什么不能传值调用(会引发无限递归,编译器一般会直接报错) 3....,但由于其没有显示定义的拷贝构造函数,编译器先给Date类生成一个默认拷贝构造函数并赋予其默认值: 调用时由于Date类型内有一个自定义类型Time,故编译器会先跳入Time类调用拷贝构造,如下图: 看一下运行结构...用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。 注 意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。..._day; }; 配套的实现来咯~我们仅需写一个operatoroperator==,而后便只需要运用重载知识对其进行调用,便能一一实现。

    8310

    C++——拷贝构造和 运算符重载

    存在递归拷贝 d对象初始化时需要自动调用构造函数, 调用函数之前需先传参, 传参过程中又是一个拷贝构造 上面是一个严谨的分析过程,没看懂就继续往下看 d2 (d1) ——(用d1...拷贝构造d2) 对象初始化之前自动调用构造函数 调用函数之前先传参 将参数d1传给构造函数 的参数d 的过程中, 由于是传值调用,相当于将d1的拷贝传给d 即拷贝构造 —— date d (d1...) (用d1构造d) 再次进行拷贝构造 参数 d1传给 参数d 的过程中,又进行拷贝构造 无休止递归下去 2....不可以,自定义类型是自己定义的,怎么比较大小由自己规定 内置类型 是编译器自己定义的类型,它知道要怎么比 C++为了增强代码的可读性引入运算符重载,运算符重载是具有特殊函数名的函数 2....不能通过连接其他符号来创建新的操作符 (如 operator@) 2.重载操作符必须有一个类类型或者枚举类型的操作数 date 就属于是自定义类型 3.用于内置类型的操作符,其含义不能改变

    31320

    【C++ 初阶路】--- 类和对象(下)

    拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。...那么拷贝构造函数如果不是引用就会形成无穷递归调用。有人说为什么不写一个返回条件来结束递归?事实上这儿都不会进入函数的内部,每当传值传参时就会形成一个新的拷贝构造。..._day; } //调用处: d1 == d2 => operator==(d1, d2); 重载为成员函数。这里需要注意的是,左操作数是this,指向调用函数的对象。..._day; } //调用处: d1 == d2 => d1.operator==(d2); 3.2 赋值运算符重载 赋值运算符重载格式 参数类型:const T&,传递引用可以提高传参效率 返回值类型...用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。 注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

    7810

    【C++初阶】类与对象:6大默认成员函数------拷贝构造和赋值运算符重载

    一.拷贝构造函数 A.概念 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。 B.特性 1....拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用; C++规定: 内置类型直接拷贝;       自定义类型必须调用拷贝构造函数完成拷贝;...如果你的拷贝构造函数的形参不是引用,那么在传参的过程中,就会发生实参的拷贝,就又会去调用拷贝构造函数,如此往复,就形成了无穷递归,当然,编译器也不会让你传值的,它会直接报错: 3....后面接需要重载的运算符符号; 函数原型:返回值类型 operator操作符(参数列表); 运算符重载的函数的调用和一般的函数也是一样的,只不过运算符重载的函数名有点特殊而已。...,那么会自动生成的赋值运算符重载,这和拷贝构造函数类似: 1.对内置类型完成浅拷贝; 2.对自定义类型会去调用它的赋值运算符重载函数 下面是日期类的赋值运算符重载: Date& operator

    15310

    【C++】踏上C++学习之旅(八):深入“类和对象“世界,掌握编程的黄金法则(三)(内含运算符重载和拷贝构造函数)

    拷贝构造函数的参数只有一个且必须是类类对象的引用,使用传值的方式(严苛的)编译器会直接报错,因为会引发无穷的递归调用。 这里可以做一个认证以及解释。...,于是乎编译器又去调用它的拷贝构造函数…无穷无尽的调用。...具体画图展示是这样的: 那我们该如何打破上面的递归调用呢?我们说过函数调用有两种形式:传值调用和传址调用。...目的是杜绝编译器出现关于自定义类型无穷递归调用的问题。 这里还要解决一个问题就是,我不加const限定符可以吗? 答案是建议加上。为什么呢?...用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。 注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

    7900

    日期类计算器的模拟实现

    _day; } 4.赋值运算符重载 //d1 = d2 //注:1.要注意两个参数的顺序 2.这里面参数不加引用不会导致无穷递归 但为了避免拷贝构造最好加引用 Date& operator=(const...//前置++ Date& operator++() { //会调用 operator+=(int day) *this += 1; return *this; } 11.后置++的运算符重载 /...重载 //内联函数和静态成员一样 调用处展开 不进符号表 inline ostream& operator<<(ostream& out, const Date& d) { out >的运算符重载 //cin >> d1 编译器转化成operator(cin,d1) 形参中相比<< 去掉了const inline istream& operator>>(istream& in,.../会调用 operator+=(int day) *this += 1; return *this; } //后置++ —多一个int参数主要是为了和前置++进行区分 构成函数重载 Date Date

    63020

    C++初阶——(类中的默认成员函数)下

    1.2特征 1.拷贝构造构造是构造函数的一个重载形式。 2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,如果使用传值方式的话编译器会直接报错,因为这样的话会引起无穷递归调用。...解释就是,函数传值也是一种拷贝,每次传值都会调用拷贝构造,就会一直调用递归。 正确写法: Date(const Date& d) { _year = d....3.用户没有显示实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字拷贝,但是要注意的是:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重新完成拷贝。 注意!...C++规定:后置++在重载时多增加一个int类型的参数,但调用函数时不用传第,编译器会自动传递。...但是如果我们只写了非const成员函数,却用const对象去调用那么在编译阶段系统会报错 4.取地址及const取地址操作符重载 这两个默认成员函数一般不用重新定义,编译器默认会生成。

    9110

    Java 设计模式系列(17) —— 解释器模式

    解释器模式 解释器模式是一种按照规定语法进行解析的方案。 解释器模式的定义: 给定一门语言,定义它的文法的一种表示并定义一个解释器,该解释器用来表示解释语言中的句子。...解释器模式的参与者: Abstract Expression 抽象解释器角色:该角色声明一个所有具体表达式角色所需要的的接口 TerminalExpression 终结符表达式:该角色实现了抽象表达式所需要的接口...Nonterminal 非终结符表达式:该角色是一个具体角色, Context 环境角色:Context 角色提供一些解释器之外的全局信息 解释器模式的简单示例 抽象解释器模式 public interface...= elements[i]; if(OperatorUtil.isOperator(operator)) { left = this.s.pop(); right = new NumInterpreter...解释器模式的优点 简单的语法分析工具 优秀的扩展性 解释器模式的缺点 解释器模式会引起类膨胀 解释器模式采用递归调用的方法 解释器模式会采用大量递归和循环,效率低下 解释器模式的使用场景 重复发生的问题可以使用解释器模式

    28410

    【C++】STL 算法 ⑥ ( 二元谓词 | std::sort 算法简介 | 为 std::sort 算法设置 二元谓词 排序规则 )

    函数调用操作符 的 函数对象 / 仿函数 , 有 operator() 函数 ; " 谓词 ( Predicate ) " 通常被设计成可以接受一定数量的参数 一元谓词 : 接受一个参数 二元谓词 :..., 这两个 迭代器 定义了一个需要排序的元素范围 , 注意 这是一个 前闭后开区间 [_First, _Last) ; _First 迭代器 指向第一个需要排序的元素 ; _Last 迭代器 指向最后一个元素之后的位置...; sort 算法 还可以接受一个 可选 的第三个参数 , 即 比较函数 , 该函数用于定义排序的规则 ; 如果不提供 排序规则 , sort 会 默认使用 operator重载操作符函数 对元素进行比较...) , 其中 n 是待排序元素的数 , 这是 " 快速排序 Quicksort " 算法 的时间复杂度 ; 在实际应用场景中 , 排序的性能可能会受到数据分布 , 元素类型以及比较函数的影响 , 如 递归层次比较深...} }; 在该 二元谓词 的 重载 函数调用操作符 函数中 , 接收 2 个元素 , 返回 第一个元素 是否 小于第二个元素 , 这是进行 从小到大 排序的 规则 ; 然后 , 创建一个 vector

    26610

    C++类和对象(中)

    , 就会由编译器自动生成,这是祖师爷制定的规则;假如我们写了,同时也满足默认构造函数的需求,编译器就会以我们写的为准,并转而调用我们写的默认构造函数 注:默认构造函数就是调用时,不需要传参的构造函数...析构函数不支持重载,毕竟不能对同一个对象销毁多次 析构函数也有一种特殊形式:默认析构函数 不过因为析构函数不支持重载,所以默认与否已经不重要了,如果我们写了,编译器就用我们写的默认析构函数,否则就用编译器自动生成的...默认析构函数也存在默认构造函数的坑:对内置类型不作处理 ️默认析构函数 如果我们没写,编译器会自动生成默认析构函数,假如我们写了,编译器就会用我们写的 注:默认析构函数是在对象生命周期结束时自动调用...️无穷递归 所谓无穷递归问题就是指设计拷贝构造函数时,参数没有设为引用 如下所示: SeqList(SeqList tmp) { //此时必然会引发无穷递归问题 //…… } 问题出现原因..._day; //同上 return tmp; //tmp 为临时变量,不能传引用返回 } 此时就可以正常使用 d1 - d2 了 注:运算符重载和函数重载没有关系 ️operator操作符 operator

    23110

    C++初阶类与对象(三):详解复制构造函数和运算符重载

    取地址操作符重载 1.拷贝构造函数 1.1引入和概念 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用(是构造函数的重载...拷贝构造函数的参数只有一个且必须是类类型对象的引用(&),使用传值方式编译器直接报错,因为会引发无穷递归调用 为什么会无限递归:当我们传值调用函数时,首先传参–>因为是传值会调用新的一个拷贝构造–>...此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝...注意:内置类型成员变量是直接赋值的(浅拷贝),而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值(跟拷贝构造的行为类似,内置类型值拷贝,自定义类型调用他的赋值) 既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了...int类型的参数,但调用函数时该参数不用传递,编译器自动传递 Date operator++(int)// 前置++和后置++都是一元运算符,加个int为了让前置++与后置++形成能正确重载 {

    21610

    【C++】拷贝构造函数和赋值运算符重载详解

    ,因为会引发无穷递归调用。...(C++规定自定义类型传值传参时都会调用它的拷贝构造,因为传值传参时,形参相当于一份拷贝,如果拷贝构造函数也是用传值的形式写的,那么它会继续寻找真正的拷贝构造函数,造成无穷递归) 传值的后果: 若未显式定义...用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。 注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。...后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器 //自动传递 // 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给...,C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给

    25110

    【C++课程学习】:类和对象(拷贝构造和运算符重载)

    因为他属于构造函数,所以我们传参时满足这一特点,编译器就会调用这个构造函数。 特点一: 拷贝构造是构造函数的一种重载形式。 特点二: 拷贝构造的参数只有一个,并且一定要是同类型的对象的引用。...比如: Data (const Data& d){ …… } 特点三: 如果是传值拷贝构造,那么就会发生无穷递归。...运算符重载是特殊函数名的函数,有返回类型和参数,返回类型和参数与普通的函数差不多。 ●函数名:operator+要重载的运算符。 ●原型:返回类型 函数名(参数列表)。...●赋值运算符只能重载成类的成员函数,不能重载为全局函数。 因为如果重载为全局函数,这时候在类里面没有显示实现,所以编译器会自己生成一个赋值运算符。...这样我们调用赋值的时候,编译器就不知道去调用哪个赋值函数。 ●编译器自己生成的赋值运算符,对于内置类型,也是去按内存的字节序进行赋值。对应自定义类型,那么就去调用它的赋值运算符函数。

    7810

    【C++】类和对象(中)

    对象实例化时编译器自动调用对应的构造函数。 构造函数可以重载。...d1对象调用了编译器生成的默认构造函数,但是d1对象*year/*month/_day,依旧是随机值。...拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。...对于第2点,采用传值方式编译器会报错(编译器检查比较严格),如果不报错就会引发无穷递归调用: 正确的做法是引用: 这里存在一个问题:为什么传值会引发无穷递归呢(当然我们这里的编译器有检查)❓ 传值传参会引发对象的拷贝...; 这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容。

    1.2K30

    自制计算器——《自制编程语言》二

    本书(本系列)的语法图丽中,非终结符用长方形表示,终结符(记号)用椭圆形表示。     正如语法图表示,我们借助递归下降分析法读入记号,然后执行语法分析,这就是我们将要编写的语法分析器。    ...递归下降分析法中,一个非终结符总对应一个处理函数,语法图里出现非终结符就代表这个函数被调用。...完整代码如下: 根据语法图可以看到,当命中非终结符时,会通过递归的方式调用其下级函数,因此这种解析器称为递归下降解析器。 自此,语法解析器已经完成。 parser.h: ?...递归下降分析会按自上而下的顺序生成分析树,所以称为递归“下降”解析器或递归“向下”解析器。而LR解析器则按照自下而上的顺序,也称为“自底而上”解析器。    ...其实Pascal并没有从一开始就强行将其区分,而是逆转思路,引入了一个同时代表“赋值语句或过程调用”的非终结符,然后在下一个记号读入后再将其分开。

    1.6K20

    类和对象(2)

    1 拷贝构造函数是构造函数的一个重载 2 拷贝构造函数的第一个参数必须是类类型对象的引用,且任何额外的参数都有默认值,使用传值方式编译器直接报错,因为语法层面会引发无穷递归调用 每次调用拷贝构造要先传值传参...,传值传参是一种拷贝, 又形成一个新的拷贝构造函数,就形成了无穷递归。...关键字operator后面接需要重载的运算符符号 重载运算符函数的参数个数和该运算符作用的运算对象数量一样多。...注意以上5个运算符不能重载。 一个类需要重载哪些运算符,是看哪些运算符重载后有意义,比如Date类重载operator-就有意 义,但是重载operator+就没有意义。...class Date { public : Date* operator&() { return this ;这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需

    9410
    领券