c++工作中遇到的细节问题汇总(一)

本文总结了C++编程中的一些常见细节问题,包括头文件的编译生成的.gch缓存,inline函数的重定义,内存区域划分,以及如何避免在析构函数中对同一对象多次delete,提供了理解和解决这些问题的要点。

1.关于xxx.h.gch

编译的时候切记不要把头文件编译进去,生成的xxx.h.gch文件是一种缓存,其后编译文件时调用头文件便一直是该缓存。

2.关于inline函数的重定义问题

inline.h

  1 #pragma once
  2                            
  3 inline int add(int a,int b)//如果这里不使用内联函数,将导致重定义问题                                                           
  4 {
  5     return a+b;            
  6 }


inline.cc

  1 #include "inline.h"


testInline.cc

  1 #include "inline.h"        
  2 #include <iostream>        
  3 using std::cout;           
  4 using std::endl;
  5 
  6 inline int add(int,int);   
  7 int main()
  8 {
  9     cout<<add(3,4)<<endl;
 10     return 0;                                                                  
 11 }

3.C++定义的变量所在的内存区

内存区的划分:数据区,代码区,BSS区,堆,栈

#include <stdio.h>
#include <string.h>

#include <iostream>
using std::cout;
using std::endl;

int a = 1;//全局静态区
char * p1;//全局变量如果没有显式进行初始化,系统也会设置默认值
 
int test0(void)
{
	int b = 2;
	const char * p2 = "hello,world";//文字常量区
	char str[] = "hello,world";//栈区
	//str = 0x1000;//str 常量
	
	char * p3;//野指针
	
	p3 = new char[20]();//堆区

	strcpy(p3, "hello,world");//与以上p2所指的"hello,world"为同一个

	static int c = 100;//局部静态变量, 全局/静态区
	++c;

	printf("sizeof(str) = %lu\n", sizeof(str));
	printf("sizeof(p2) = %lu\n", strlen(p2));
 
	printf("&a = %p\n", &a);
	printf("&b = %p\n", &b);
	printf("p1 = %p\n", p1);
	printf("&p1 = %p\n", &p1);
	printf("p2 = %p\n", p2);
	printf("&p2 = %p\n", &p2);
	printf("str = %p\n", str);
	printf("p3 = %p\n", p3);
	//*p3 = '1';//error 野指针
	printf("&p3 = %p\n", &p3);
	printf("&c = %p\n", &c);
	printf("address(hello,world) = %p\n", "hello,world");
	printf("address(test0) = %p\n", &test0);//程序代码区

	return 0;
}

int main(void)
{
	test0();
	return 0;
}

4.防止在析构函数中delete多次

#include <string.h>
#include <iostream>
using std::cout;
using std::endl;


class Computer
{
public:
	Computer(const char * brand, double price)
	: _brand(new char[strlen(brand) + 1]())  //浅拷贝, 只传地址
	, _price(price)
	{
		strcpy(_brand, brand);
		cout << "Computer(const char *, double)" << endl;
	}
	

	void print()
	{
		cout << "   brand:" << _brand << endl
			 << "   price:" << _price << endl;
	}

	//对象销毁的过程中会自动调用析构函数
	
#if 0
	void release()
	{
		delete [] _brand;
	}
#endif

	~Computer()
	{	//析构函数的作用:是用来回收对象申请的资源
		if(_brand) {//防止delete多次
			delete [] _brand;
			_brand = nullptr;//NULL
		}
		cout << "~Computer()" << endl;
	}

private:
	char * _brand;
	double _price;
};

//Computer pc2("Xiaomi", 7500);
 
int test0(void)
{
	{
	Computer pc1("MateBook", 6666);
	cout << ">> pc1: " << endl;
	pc1.print();
	}

	cout << ">> pc2: " << endl;
//	pc2.print();

	//堆空间的对象的销毁,需要手动执行
	Computer * pc3 = new Computer("Thinkpad", 7777);
	cout << ">> pc3: " << endl;
	pc3->print();

	delete pc3;//不要忘了, 执行delete表达式的过程中,就会调用析构函数

	static Computer pc4("Macbook pro", 20000);
	cout << ">> pc4: " << endl;
	pc4.print();

	return 0;
}

void test1()
{
	Computer * pc3 = new Computer("Thinkpad", 7777);
	cout << ">> pc3: " << endl;
	pc3->print();
	pc3->~Computer();//该语句被执行之后,对象是没有被销毁的
        //这里手动销毁调用delete,执行完毕自动调用时调用delete,故delete了两次
        //所以要采用如上析构函数的写法
	delete pc3;
}

void test2()
{
	Computer pc1("MateBook", 6666);
	cout << ">> pc1: " << endl;
	pc1.print();
	pc1.~Computer();//析构函数可以主动调用,但不推荐这样做
				    //析构函数应该让其自动执行
	//pc1.release();
}

int main(void)
{
	//test1();
	test2();
	return 0;
}

在堆空间,栈空间,静态区,全局区都可以自动调用析构函数,但是在堆空间只有delete时会调用堆空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值