应用层对new,free混合搭配的分析

补充说明

malloc一个指针delete / delete[] 掉 : POD类型没事,有非travel析构函数的会出事

free

free(NULL)合法
free(野指针)大概率崩溃,小概率没事,具体要分析源代码
连续两次free,在一些非常有限的情况下,不会崩溃
多次free,在大多数情况下会导致崩溃

手动调用构造和析构函数

比较诡异,c++可以显示调用析构函数,比如A a;a.~A(),但是不能显式调用构造函数
并且,编译器会在对象生命周期结束时,自动调用构造函数
利用定位new表达式可以显示调用构造函数,定位new就这一个用途

operator new

operator new是可以重载的函数

首先new operator 和 operator new不一样,不清楚的百度一下
operator new是一个可以用户重载的函数,负责开辟空间(不负责初始化、调用构造函数)
全局operator new一般默认调用malloca开辟空间,全局operator new不应该被重载

但是,可以在类里面重载operator new

编译器在new class()的时候会自动调用重载的operator new,分配空间

特别是,在基类里面重载operator new,会应用到所有派生类

这是一种特别优雅的做法,应用于大规模库比如MFC
operator new重载有一些规定,自己百度

new operator

new operator是运算符

c++标准保证了new operator的行为 :先分配内存,然后初始化
new的时候,本质上先调用operator new分配内存,然后再调用构造函数

new type[]

对于有构造函数的类型,new []申请 4字节 + size大小的内存,4字节用来存储数组长度
为什么要存储数组长度?构造/析构的时候要用
对于没有构造函数的类型,编译器不浪费空间记录数组长度
auto p = new 没有构造函数的POD类型[100];free(p);也没事
所以

auto p = new char[100]();
free(p);
// 没问题 
auto p = new string[100]();
free(p);
// 有问题

面试问题,当free,new这些混用起来时,会出现什么情况?

捋到这里,这些问题就很清晰了
无非两个问题

1.对象有没有正确构造、析构

2.free,delete,delete []的时候,会不会导致free()崩溃

如何限制对象仅仅在堆上生长

采用 CRTP,很方便
private 析构函数也行,缺点是不能正常delete
CRTP真好用

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
template<typename T>
struct base
  {
  	template<typename ...Args>
  	static T* create(Args &&... args)
  	  {
  	  	return new T(std::forward<Args>(args)...);
		}
  };
struct son : base<son>
  {	
    friend class base<son>;
  	ll val;
  	protected :
	  	son(ll val)
	  	  : val(val)
	  	    {}
	  	son(son const& rhs)
	  	  {}
  };
int main()
  {
  	auto p = son::create(10);
  	cout << p -> val << endl;
	delete p;
	return 0;
  }

如何限制对象仅仅在栈上生长

思路就是找operator new下手,注意重载格式

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
struct base
  {
    void* operator new(size_t) = delete;      // 注意函数的第一个参数和返回值都是固定的  
    void  operator delete(void*) = delete;    // 重载了new就需要重载delete  
  };
struct son : base
  {	
  	ll val;
  	son(ll val)
  	  : val(val)
  	    {}
  	son(son const& rhs)
  	  {}
  };
int main()
  {
  	son a(10);
  	cout << a.val << endl;
  	//auto  p = new son(10);
	return 0;
  }
posted @ 2021-06-05 11:14  XDU18清欢  阅读(102)  评论(0)    收藏  举报