C++避坑指南

本文是C++学习者的一份避坑指南,涵盖了函数声明与对象定义、静态对象初始化顺序、类型转换(包括隐式和显示转换)、inline内联、名称查找、智能指针(如std::auto_ptr、std::shared_ptr、std::unique_ptr)以及lambda表达式的使用注意事项。文章通过实例分析了C++中常见错误和潜在问题,帮助开发者避免编程陷阱。
摘要由CSDN通过智能技术生成


 640?wx_fmt=gif




导语:如果,将编程语言比作武功秘籍,C++无异于《九阴真经》。《九阴真经》威力强大、博大精深,经中所载内功、轻功、拳、掌、腿、刀法、剑法、杖法、鞭法、指爪、点穴密技、疗伤法门、闭气神功、移魂大法等等,无所不包,C++亦如是。


C++跟《九阴真经》一样,如果使用不当,很容易落得跟周芷若、欧阳锋、梅超风等一样走火入魔。这篇文章总结了在学习C++过程中容易走火入魔的一些知识点。为了避免篇幅浪费,太常见的误区(如指针和数组、重载、覆盖、隐藏等)在本文没有列出,文中的知识点也没有前后依赖关系,各个知识点基本是互相独立,并没有做什么铺垫,开门见山直接进入正文。


目录

1 函数声明和对象定义

2 静态对象初始化顺序

3 类型转换

3.1 隐式转换

3.2 显示转换

4 inline内联

5 名称查找

5.1 受限名称查找

5.2 非受限名称查找

6 智能指针

6.1 std::auto_ptr

6.2 std::shared_ptr

6.3 std::unique_ptr

7 lambda表达式


1 函数声明和对象定义

对象定义写成空的初始化列表时,会被解析成一个函数声明。可以采用代码中的几种方法定义一个对象。

 
 
//这是一个函数声明	
//不是一个对象定义	
string foo();	
	
	
//函数声明	
string foo(void);	
	
	
//对象定义几种方法	
string foo;	
string foo{ };//c++11	
string *foo = new string;	
string *foo = new string();	
string *foo = new string{ };//c++11

(左滑可以查看全部代码,下同)


2 静态对象初始化顺序

在同一个编译单元中,静态对象的初始化次序与其定义顺序保持一致。对于作用域为多个编译单元的静态对象,不能保证其初始化次序。如下代码中,在x.cpp和y.cpp分别定义了变量x和y,并且双方互相依赖。

 
 
//x.cpp	
extern int y;	
int x = y + 1;

x.cpp中使用变量y来初始化x


 
 
//y.cpp	
extern int x;	
int y = x + 1;

y.cpp中使变量x来初始化y

 
 
//main.cpp	
extern int x;	
extern int y;	
int main()	
{	
    cout << "x = " << x << endl;	
    cout << "y = " << y << endl;	
    return 0;	
}


如果初始化顺序不一样,两次执行的结果输出不一样,如下所示:

 
 
g++ main.cpp x.cpp y.cpp	
./a.out 	
x = 1	
y = 2


 
 
g++ main.cpp y.cpp x.cpp	
./a.out 	
x = 2	
y = 1


如果我们需要指定依赖关系,比如y依赖x进行初始化,可以利用这样一个特性来实现:函数内部的静态对象在函数第一次调用时初始化,且只被初始化一次。使用该方法,访问静态对象的唯一途径就是调用该函数。改写后代码如下所示:

 
 
//x.h	
extern int &getX();	
//x.cpp	
int &getX()	
{	
    static int x;	
    return x;	
}

getX()函数返回x对象


 
 
//y.h	
extern int &getY();	
//y.cpp	
#include "x.h"	
int &getY()	
{	
    static int y = getX() + 1;	
    return y;	
}

y对象使用x对象进行初始化


 
 
//main.cpp	
int main()	
{	
    cout << "x = " << getX() << endl;	
    cout << "y = " << getY() << endl;	
    return 0;	
}

打印x和y值。通过这种方式,就保证了x和y的初始化顺序。


 
 
g++ main.cpp x.cpp y.cpp	
./a.out 	
x = 0	
y = 1


 
 
g++ main.cpp y.cpp x.cpp	
./a.out 	
x = 0	
y = 1


3 类型转换


这里只描述自定义类的类型转换,不涉及如算数运算的类型自动提升等。


3.1 隐式转换

C++自定义类型在以下两种情况会发生隐式转换:

1) 类构造函数只有一个参数或除第一个参数外其他参数有默认值;
2) 类实现了operator type()函数;

 
 
class Integer	
{	
public:	
    Integer() : m_value(0) {  }	
    //int --> Integer	
    Integer(int value) : m_value(value)	
    {	
        cout << "Integer(int)" << endl;	
    }	
	
	
    //Integer -->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值