C++碎片化知识点记录(1)

一.如何让类的对象只创建在栈上(或堆上)

这个是一个比较冷门的知识点,目前个人整理出了几种办法。

1.只分配在栈上:对new关键字重载并放在protected域

因为C++只有用new的关键字生成的对象才是放在堆上的,现在可以对new进行重载,将其放在private内,这样我们就调用不了new,这样也就可以限制程序将类对象分配到堆里头了。而由于new跟delete是配套出现的,重载new还需要重载delete。

参考链接:《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?_hxz_qlh的博客-CSDN博客

class A  
{  
protected:  
    void* operator new(size_t t){}     // 注意函数的第一个参数和返回值都是固定的  
    void operator delete(void* ptr){} // 重载了new就需要重载delete  
public:  
    A(){}  
    ~A(){}  
};

2.只分配在堆上:将析构函数放在privete域

编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性,其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。因此,将析构函数设为私有,类对象就无法建立在栈上了。


class A
{
public:
    A(){}
    void destory(){delete this;}
private:
    ~A(){}

但是这个时候不能用delete,只能手动调用destory函数释放内存了。

3.借鉴单例模式思想:只用函数去生成对象或释放内存

将构造函数放置到private域当中,然后通过一个静态函数去控制分配在栈上还是堆上。

class Point1
{
protected:
    Point1() {};//将构造函数私有化
public:
    ~Point1() {}
    int k = 9;
    static Point1 Produce1() {//控制分配在栈上
        Point1 p;
        return p;
    }
        static Point1* Produce2() {//控制分配在堆上
        Point1 *p=new Point1;
        return p;
    }
};

4.使用placement new

参考自:C++中使用placement new_edenliuJ的博客-CSDN博客_c++ new placement

一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间。申请所得的空间的位置是根据当时的内存的实际使用情况决定的。但是,在某些特殊情况下,可能需要在已分配的特定内存创建对象,这就是所谓的“定位放置new”(placement new)操作。 
定位放置new操作的语法形式不同于普通的new操作。例如,一般都用如下语句A* p=new A;申请空间,而定位放置new操作则使用如下语句A* p=new (ptr)A;申请空间,其中ptr就是程序员指定的内存首地址。考察如下程序。

#include <iostream>
using namespace std;
 
class A
{
public:
	A()
	{
		cout << "A's constructor" << endl;
	}
 
 
	~A()
	{
		cout << "A's destructor" << endl;
	}
	
	void show()
	{
		cout << "num:" << num << endl;
	}
	
private:
	int num;
};
 
int main()
{
	char mem[100];
	mem[0] = 'A';
	mem[1] = '\0';
	mem[2] = '\0';
	mem[3] = '\0';
	cout << (void*)mem << endl;
	A* p = new (mem)A;
    //或者
	//A* p = new (mem)A();
    //如果A有带参数的构造函数的话,也可以这样
    //A* p = new (mem)A(value);
    //STL的空间配置器将内存分配和构造调用分开来,需要用到placement new
	cout << p << endl;
	p->show();
	p->~A();
	getchar();
}

二、关于inline函数的优缺点

参考自:C++中的inline用法 - Boblim - 博客园

inline_百度百科

内联函数 —— C 中关键字 inline 用法解析_zqixiao_09的博客-CSDN博客_c语言 inline

1.inline函数的基本介绍

1)引入初衷:

  1. 在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数。
  2. 定义在类中的成员函数缺省都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上inline,否则就认为不是内联的。

2)运行原理

  1. inline定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换(像宏一样直接将代码复制后展开),没有了调用的开销,效率也很高。
  2. 很明显,类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
  3. inline可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员

2.相对宏定义的优点

即上面运行原理的点2和点3.

3.使用注意事项

尽管是否使用内联是编译器说的算(有的编译器会识别在内联函数超过一定长度后调用栈),但我们仍要小心使用,尤其别在里头放太多的代码或是调用复杂的迭代和递归,容易内存爆炸。

三、智能指针的循环引用问题

参考链接:C++ 智能指针(及循环引用问题)_Fly_bit的博客-CSDN博客

C++智能指针循环引用问题分析_swings_ss的博客-CSDN博客_智能指针循环引用

智能指针的循环引用问题,简单来说就是仅仅有shared_ptr会造成循环引用现象导致智能指针无法发挥其自动释放空间的功能。这时候需要使用weak_ptr来解决这种循环引用的现象。

除此之外补充一个:关于auto_ptr为什么要删除可参考:

auto_ptr - 简书

auto_ptr的缺陷在哪里?为什么不应该用? - 知乎

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值