C++知识点杂记3——局部类、位域、volatile、链接指示、枚举、定位new

本文介绍了C++的多种特性,包括局部类,其定义在函数内部,成员定义须完整;位域可减少变量内存占用,常用于底层开发;volatile保证变量读取准确性;链接指示用于调用非C++语言代码;还介绍了枚举、定位new等特性及使用注意事项。

一、局部类

局部类就是定义在函数内部的类,因为作用域只是在函数内部,所以,所有成员定义必须完整,在Qt的源码中有几处使用了局部类,见博客https://blog.youkuaiyun.com/Master_Cui/article/details/109162220

因为局部类必须定义完整,所以不能在局部类中声明static成员变量,如果定义了static成员变量,要把static成员变量的定义放在类的外部,与局部类必须完整相违背

 

二、位域

位域就是含有一定数量二进制位的变量,变量的类型通常应该是无符号整形。位域的声明形式是变量名后跟一个冒号和一个常量表达式,表达式用来指定变量所占的二进制位数

在QT的源码中,有几处使用了该技术。见博客https://blog.youkuaiyun.com/Master_Cui/article/details/109007524

因为变量使用了位域后,变量所占的内存就会变小,位域一般在底层开发中用的比较多。

示例

union uploaddata 
{
	unsigned char buffer[4];
	
	struct datastr
	{
		unsigned int audiocount:3;
		unsigned int videocount:3;
	}data;
};

上述代码中,通过位域表示audio和video的数量,并通过buffer把数据发送给其他模块

 

三、volatile

如果一个变量是volatile的,那么表示告诉编译器不应该对这样的变量进行优化,这样,每次取volatile变量的值时,都会从内存中进行存取,而不会到缓存中存取。从而保证读取volatile变量值的准确性

一般也是在底层开发中用得较多

 

四、链接指示

C++有时需要使用其他语言的代码,在C++中,使用链接指示指出其他非C++语言的代码

最常见的是调用C编写的函数,此时就需要用extern "C"

示例

extern "C" {
	int strcmp(const char *str1, const char *str2);
	char *strcat(char *des, const char* src);
}

上述两个函数就被放在extern "C"的链接指示中,表示是两个C语言函数

 

因为C语言不支持重载,所以extern "C"中不能有同名函数

extern "C" {
	void func();
	void func(int );
}

一切C++特有而C中没有的特性都不能加在extern "C"中

 

五、枚举

枚举就是一系列整形值的集合。当对枚举进行初始化时,要使用枚举成员,即使使用的整形值和枚举成员的值相等,也不能用整形只初始化枚举对象

示例

enum state
{
	stop=1,
	pause=2,
	play=3
};

int main(int argc, char const *argv[])
{
	state s1=stop;
	s1=3;
}

 

如果硬要使用整形值初始化枚举对象,那么使用static_cast吧

int main(int argc, char const *argv[])
{
	state s1=stop;
	s1=static_cast<state>(3);
}

 

六、定位new

一般的new运算符负责在heap堆中找到一个足以能够满足要求的内存块。new运算符还有另一种变体:定位new运算符(placement new),它能够在分配内存时指定内存的位置。

定位new有以下几种形式

place_address是个地址,指向内存空间,所以,定位new只构造对象并不分配内存

示例

class test
{
public:
	test(){}
	~test(){}
};

int main(int argc, char const *argv[])
{
	char buffer[256];
	//char *buffer=new char[256];
	char *p=buffer;
	int *pi=new(p) int;
	cout<<pi<<endl;
	p+=sizeof(int);

	int *pai=new(p) int[10];
	p+=sizeof(int[10]);
	cout<<pai<<endl;

	test *ptest=new(p) test();
	cout<<ptest<<endl;
	ptest->~test();
	//delete ptest;
	//delete buffer;
}

 

buffer已经在栈上分配内存,所以,buffer在代码块结束后,会自动释放;

如果buffer通过new分配,则需要使用delete释放

 

对于正常new得到的类对象。delete时会先隐式调用析构函数释放对象,然后调用operator delete释放内存空间

但是对于定位new构造的对象要显式调用它们的析构函数来销毁对象即可,因为定位new不负责分配内存(析构函数只是销毁对象,并不释放对象的内存

所以,不能使用delete释放定位new创建的对象的内存,因为delete的这两个动作被拆开了

使用delete会造成错误。

所以,对象需要在buffer释放前,显式的调用析构函数

 

参考

《C++ Primer》

https://blog.youkuaiyun.com/qq2071114140/article/details/89287373

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值