- 浏览: 1505123 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (516)
- Java (49)
- Java/Struts 2.0 (25)
- Java/Spring、Spring MVC (11)
- Java/Quartz (3)
- Java/Lucene (6)
- Java/Hibernate (19)
- Java/openJPA (7)
- Java/DWR (7)
- Java/Security、Spring Security/OAuth2 (6)
- Java/Threading (9)
- Java/XML (22)
- java/design pattern (4)
- Android (2)
- JavaScript (46)
- jquery (3)
- DB/MySQL (23)
- DB/Oracle (16)
- PHP (25)
- CSS (20)
- Linux (38)
- C/C++、DLL、Makefile、VC++ (31)
- 正则 (9)
- Eclipse (4)
- 安全、网络等概念 (25)
- 集群 (7)
- 网页 (5)
- 视频\音频 (1)
- HTML (6)
- 计算机数学/算法 (3)
- Virtualbox (1)
- LDAP (2)
- 数据挖掘 (6)
- 工具破解 (1)
- 其他 (13)
- Mail (1)
- 药材 (3)
- 游戏 (2)
- hadoop (13)
- 压力测试 (3)
- 设计模式 (3)
- java/Swing (2)
- 缓存/Memcache (0)
- 缓存/Redis (1)
- OSGI (2)
- OSGI/Gemini (0)
- 文档写作 (0)
- java/Servlet (3)
- MQ/RabbitMQ (2)
- MQ/RocketMQ (0)
- MQ/Kafka (1)
- maven (0)
- SYS/linux (1)
- cache/redis (1)
- DB/Mongodb (2)
- nginx (1)
- postman (1)
- 操作系统/ubuntu (1)
- golang (1)
- dubbo (1)
- 技术管理岗位 (0)
- mybatis-plus (0)
最新评论
-
pgx89112:
大神,请赐我一份这个示例的项目代码吧,万分感谢,1530259 ...
spring的rabbitmq配置 -
string2020:
不使用增强器 怎么弄?
OpenJPA的增强器 -
孟江波:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!4 ...
spring的rabbitmq配置 -
eachgray:
...
spring-data-redis配置事务 -
qljoeli:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!1 ...
spring的rabbitmq配置
C++ 的 11 个注意要点
下面的这些要点是对所有的
C++
程序员都适用的。我之所以说它们是最重要的,是因为这些要点中提到的是你通常在
C++
书中或网站上无法找到的。如:指向成员的指针,这是许多资料中都不愿提到的地方,也是经常出错的地方,甚至是对一些高级的
C++
程序员也是如此。
这里的要点不仅仅是解释怎样写出更好的代码,更多的是展现出语言规则里面的东西。很显然,它们对
C++
程序员来说是永久的好资料。我相信这一篇文章会使你收获不小。
首先,我把一些由不同层次的
C++
程序员经常问的问题归到一起。我惊奇的发现有很多是有经验的程序员都还没意识到
.h
符号是否还应该出现在标准头文件中。
要点
1:
<iostream.h>
还是
<iostream>?
很多
C++
程序员还在使用
<iostream.h>
而不是用更新的标准的
<iostream>
库。这两者都有什么不同呢?首先,
5
年前我们就开始反对把
.h
符号继续用在标准的头文件中。继续使用过时的规则可不是个好的方法。从功能性的角度来讲,
<iostream>
包含了一系列模板化的
I/O
类,相反地
<iostream.h>
只仅仅是支持字符流。另外,输入输出流的
C++
标准规范接口在一些微妙的细节上都已改进,因此,
<iostream>
和
<iostream.h>
在接口和执行上都是不同的。最后,
<iostream>
的各组成都是以
STL
的形式声明的,然而
<iostream.h>
的各组成都是声明成全局型的。
因为这些实质上的不同,你不能在一个程序中混淆使用这两个库。做为一种习惯,在新的代码中一般使用
<iostream>
,但如果你处理的是过去编写的代码,为了继承可以用继续用
<iostream.h>
旧保持代码的一致性。
要点
2
:用引用传递参数时应注意的地方
在用引用传递参数时,最好把引用声明为
const
类型。这样做的好处是:告诉程序不能修改这个参数。在下面的这个例子中函数
f()
就是传递的引用:
void f(const int & i);
int main()
{
f(2); /* OK
*/
}
这个程序传递一个参数
2
给
f()
。在运行时,
C++
创建一个值为
2
的
int
类型的临时变量,并传递它的引用给
f().
这个临时变量和它的引用从
f()
被调用开始被创建并存在直到函数返回。返回时,就被马上删除。注意,如果我们不在引用前加上
const
限定词,则函数
f()
可能会更改它参数的值,更可能会使程序产生意想不到的行为。所以,别忘了
const
。
这个要点也适用于用户定义的对象。你可以给临时对象也加上引用如果是
const
类型:
struct A{};
void f(const A& a);
int main()
{
f(A()); //
OK,
传递的是一个临时
A
的
const
引用
}
要点
3
:
“
逗号分离
”
表达形式
“
逗号分离
”
表达形式是从
C
继承来的,使用在
for-
和
while-
循环中。当然,这条语法规则被认为是不直观的。首先,我们来看看什么是
“
逗号分离
”
表达形式。
一个表达式由一个或多个其它表达式构成,由逗号分开,如:
if(++x, --y,
cin.good()) //
三个表达式
这个
if
条件包含了三个由逗号分离的表达式。
C++
会计算每个表达式,但完整的
“
逗号分离
”
表达式的结果是最右边表达式的值。因此,仅当
cin.good()
返回
true
时,
if
条件的值才是
true
。下面是另一个例子:
int j=10;
int i=0;
while( ++i, --j)
{
//
直到
j
=
0
时,循环结束,在循环时,
i
不断自加
}
要点
4
,使用全局对象的构造函数在程序启动前调用函数
有一些应用程序需要在主程序启动前调用其它函数。如:转态过程函数、登记功能函数都是必须在实际程序运行前被调用的。最简单的办法是通过一个全局对象的构造函数来调用这些函数。因为全局对象都是在主程序开始前被构造,这些函数都将会在
main()
之前返回结果。如:
class Logger
{
public:
Logger()
{
activate_log();//
译者注:在构造函数中调用你需要先运行的函数
}
};
Logger log; //
一个全局实例
int main()
{
record *
prec=read_log();//
译者注:读取
log
文件数据
//..
程序代码
}
全局对象
log
在
main()
运行之前被构造,
log
调用了函数
activate_log()
。从而,当
main()
开始执行时,它就可以从
log
文件中读取数据。
毫无疑问地,在
C++
编程中内存管理是最复杂和最容易出现
bug
的地方。直接访问原始内存、动态分配存储和最大限度的发挥
C++
指令效率,都使你必须尽力避免
有关内存的
bug
。
要点
5
:避免使用复杂构造的指向函数的指针
指向函数的指针是
C++
中可读性最差的语法之一。你能告诉我下面语句的意思吗?
void (*p[10]) (void (*)());
P
是一个
“
由
10
个指针构成的指向一个返回
void
类型且指向另一个无返回和无运算的函数的数组
”
。这个麻烦的语法真是让人难以辨认,不是吗?你其实可以简单的通过
typedef
来声明相当于上面语句的函数。首先,使用
typedef
声明
“
指向一个无返回和无运算的函数的指针
”
:
typedef void (*pfv)();
接着,声明
“
另一个指向无返回且使用
pfv
的函数指针
”
:
typedef void (*pf_taking_pfv) (pfv);
现在,声明一个由
10
个上面这样的指针构成的数组:
pf_taking_pfv p[10];
与
void (*p[10])
(void (*)())
达到同样效果。但这样是不是更具有可读性
了!
要点
6
:指向成员的指针
一个类有两种基本的成员:函数成员和数据成员。同样的,指向成员的指针也有两种:指向函数成员的指针和指向数据成员的指针。后则其实并不常用,因为类一般是不含有公共数据成员的,仅当用在继承用
C
写的代码时协调结构(
struct)
和类
(class)
时才会用到。
指向成员的指针是
C++
语法中最难以理解的构造之一,但是这也是一个
C++
最强大的特性。它可以让你调用一个类的函数成员而不必知道这个函数的名字。这一个非常敏捷的调用工具。同样的,你也可以通过使用指向数据成员的指针来检查并改变这个数据而不必知道它的成员名字。
指向数据成员的指针
尽管刚开始时,指向成员的指针的语法会使你有一点点的迷惑,但你不久会发现它其实同普通的指针差不多,只不过是
*
号的前面多了
::
符号和类的名字,例:定义一个指向
int
型的指针:
int * pi;
定义一个指向为
int
型的类的数据成员:
int A::*pmi; //pmi
是指向类
A
的一个
int
型的成员
你可以这样初始化它:
class A
{
public:
int
num;
int x;
};
int A::*pmi = & A::num;
上面的代码是声明一个指向类
A
的一个
int
型的
num
成员并将它初始化为这个
num
成员的地址
.
通过在
pmi
前面加上
*
你就可以使用和更改类
A
的
num
成员的值:
A a1, a2;
int n=a1.*pmi; //
把
a1.num
赋值给
n
a1.*pmi=5; //
把
5
赋值给
a1.num
a2.*pmi=6; //
把
6
赋值给
6a2.num
如果你定义了一个指向类
A
的指针,那么上面的操作你必须用
->*
操作符代替:
A * pa=new A;
int n=pa->*pmi;
pa->*pmi=5;
指向函数成员的指针
它由函数成员所返回的数据类型构成,类名后跟上
::
符号、指针名和函数的参数列表。举个例子:一个指向类
A
的函数成员(该函数返回
int
类型)的指针:
class A
{
public:
int func
();
};
int (A::*pmf) ();
上面的定义也就是说
pmf
是一个指向类
A
的函数成员
func()
的指针
.
实际上,这个指针和一个普通的指向函数的指针没什么不同,只是它包含了类的名字和
::
符号。你可以在在任何使用
*pmf
的地方调用这个函数
func()
:
pmf=&A::func;
A a;
(a.*pmf)(); //
调用
a.func()
如果你先定义了一个指向对象的指针,那么上面的操作要用
->*
代替:
A *pa=&a;
(pa->*pmf)(); //
调用
pa->func()
指向函数成员的指针要考虑多态性。所以,当你通过指针调用一个虚函数成员时,这个调用将会被动态回收。另一个需要注意的地方,你不能取一个类的构造函数和析构函数的地址。
要点
7
、避免产生内存碎片
经常会有这样的情况:你的应用程序每运行一次时就因为程序自身缺陷而产生内存漏洞而泄漏内存,而你又在周期性地重复着你的程序,结果可想而知
,
它也会使系统崩溃。但怎样做才能预防呢?首先,尽量少使用动态内存。在大多数情况下,你可能使用静态或自动存储或者是
STL
容器。第二,尽量分配大块的内存而不是一次只分配少量内存。举个例子:一次分配一个数组实例所需的内存,而不是一次只分配一个数组元素的内存。
要点
8
、是
delete
还是
delete[]
在程序员中有个荒诞的说法:使用
delete
来代替
delete[]
删除数组类型时是可以的!
举个例子吧:
int *p=new
int[10];
delete p; //
错误,应该是:
delete[] p
上面的程序是完全错误的。事实上,在一个平台上使用
delete
代替
delete[]
的应用程序也许不会造成系统崩溃,但那纯粹是运气。你不能保证你的应用程序是不是会在另一个编译器上编译,在另一个平台上运行,所以还是请使用
delete[]
。
要点
9
、优化成员的排列
一个类的大小可以被下面的方式改变:
struct A
{
bool a;
int b;
bool c;
}; //sizeof (A) == 12
在我的电脑上
sizeof (A)
等于
12
。这个结果可能会让你吃惊,因为
A
的成员总数是
6
个字节:
1+4+1
个字节。那另
6
字节是哪儿来的?编译器在每个
bool
成员后面都插入了
3
个填充字节以保证每个成员都是按
4
字节排列,以便分界。你可以减少
A
的大小,通过以下方式:
struct B
{
bool a;
bool c;
int b;
}; // sizeof (B) == 8
这一次,编译器只在成员
c
后插入了
2
个字节。因为
b
占了
4
个字节,所以就很自然地把它当作一个字的形式排列,而
a
和
c
的大小
1+1=2
,再加上
2
个字节就刚好按两个字的形式排列
B
。
要点
10
、为什么继承一个没有虚析构函数的类是危险的?
一个没有虚析构函数的类意味着不能做为一个基类。如
std::string,std::complex,
和
std::vector
都是这样的。为什么继承一个没有虚析构函数的类是危险的?当你公有继承创建一个从基类继承的相关类时,指向新类对象中的指针和引用实际上都指向了起源的对象。因为析构函数不是虚函数,所以当你
delete
一个这样的类时,
C++
就不会调用析构函数链。举个例子说明:
class A
{
public:
~A() //
不是虚函数
{
// ...
}
};
class B: public A //
错
; A
没有虚析构函数
{
public:
~B()
{
// ...
}
};
int main()
{
A * p = new
B; //
看上去是对的
delete p; //
错,
B
的析构函没有被调用
}
要点
11
、以友元类声明嵌套的类
当你以友元类声明一个嵌套的类时,把友元声明放在嵌套类声明的后面,而不前面。
class A
{
private:
int i;
public:
class B //
嵌套类声明在前
{
public:
B(A & a)
{ a.i=0;};
};
friend class
B;//
友元类声明
};
发表评论
-
数据结构与算法分析(C语言描述)源代码与答案
2009-12-14 11:44 6683数据结构与算法分析(C语言描述)(第二版) Mark A ... -
A new Michael Jackson song
2009-10-12 16:48 924<!-- [if gte mso 9]><x ... -
makefile 大全
2009-02-24 07:37 1141http://chenl.blogbus.com/logs ... -
Linux_Unix环境下的Make和Makefile详解
2009-02-24 07:35 1293无论是在 Linux 还是在 U ... -
运用autoconf和automake自动生成Makefile实例讲解
2009-02-24 07:30 4027运用 autoconf 和 automake ... -
makefile详解(6)
2009-02-24 07:23 1758makefile 详解( 6 ) ... -
makefile详解(5)
2009-02-24 07:22 1643<!-- --><!-- -->& ... -
makefile详解(4)
2009-02-24 07:21 1387<!-- --><!-- -->& ... -
makefile详解(3)
2009-02-24 07:20 1604<!-- --><!-- --> & ... -
makefile详解(2)
2009-02-24 07:19 1293<!-- --><!-- --> & ... -
makefile详解(1)
2009-02-24 07:18 1476makefile 详解 ... -
VC++动态链接库(DLL)编程深入浅出(二) Win32 Dynamic-Link Library
2008-08-19 14:23 7975上节给大家介绍了静态链接库与库的调试与查看( 动态链 ... -
VC++动态链接库(DLL)编程深入浅出(一) Win32 Static Library
2008-08-19 14:13 7086http://www.pconline.com.cn/pced ... -
VC++常用数据类型及其操作详解
2008-08-18 23:43 1334http://blog.csdn.net/flxyzsby/a ... -
VC++数据类型转换大全
2008-08-18 23:25 63892int i = 100; long l = 2001; f ... -
DLL导出变量
2008-08-18 16:20 2035DLL定义的全局变量可以被调用进程访问;DLL也可以访问调用进 ... -
DLL导出类
2008-08-18 16:20 2588DLL中定义的类可以在应用工程中使用。 下面的例子里,我 ... -
MFC规则DLL 概述
2008-08-18 16:19 2781MFC规则DLL的概念体现在两方面: (1) 它是MFC ... -
MFC规则DLL的创建
2008-08-18 16:18 1816我们来一步步讲述使用MFC向导创建MFC规则DLL的过程,首先 ... -
MFC规则DLL 简单的例子
2008-08-18 16:16 3913这个DLL的例子(属于静态链接到MFC 的规则DLL)中提供了 ...
相关推荐
学习C++需要注意的50要点
你最需要注意的11条要点for c++
C++多线程编程介绍,技巧以及注意要点,主要以C++11和C++14作为主要语言进行介绍。
C++多线程编程介绍,技巧以及注意要点,主要以C++11和C++14作为主要语言进行介绍。本节主要介绍原子变量和内存顺序。
C++多线程编程介绍,技巧以及注意要点,主要以C++11和C++14作为主要语言进行介绍。本节主要介绍异步编程及其技巧和常见异步框架分析。
由函数成员所返回的数据类型构成,类名后跟上::符号、指针名和函数的参数列表。举个例子:一个指向类A的函数成员(该函数返回int类型)的指针: ...另一个需要注意的地方,你不能取一个类的构造函数和析构函数的地址。
C++重要知识点分析,这正是学习以及应用过程中应该注意要点
c++ 相关的要点,注意点,区分点等,以及cpp 的相关运算符比较。
本书具有下面的一些特色: (1) 例程精练、实用、完整,易于查找本书的...值得注意的是,第一部分的内容对使用C++语言进行软件开发非常有用,一定要掌握好。对于C++Builder的高级用户,可以直接挑选感兴趣的章节阅读。
读范例金典,走开发捷径,11大类编程应用,31个主要技术方向,112个细分应用点,355个经典范例,应用为纲、范例为目,深入介绍Visual C++的约722个重要程序代码,精要阐释每个范例实现原理、开发过程和编程要点。...
本书特色 本书具有下面的一些特色: (1) 例程精练、实用、完整,易于...值得注意的是,第一部分的内容对使用C++语言进行软件开发非常有用,一定要掌握好。对于C++Builder的高级用户,可以直接挑选感兴趣的章节阅读。
C++ 全面基础知识要点之变量 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,...
一个初学者认为此书中对C++游戏编程基础知识介绍时,读者应该注意的要点
C++语言:switch语句最详细讲解。从switch语句的执行过程,switch语句的注意要点,例题讲解,作业等 。适合于中小学生,信息学爱好者。
读范例金典,走开发捷径,11大类编程应用,31个主要技术方向,112个细分应用点,355个经典范例,应用为纲、范例为目,深入介绍Visual C++的约722个重要程序代码,精要阐释每个范例实现原理、开发过程和编程要点。...
4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会...
【内容简介】 本书详细介绍了利用Visual C++进行串口通信编程的...1.3.3 RS-422与RS-485网络安装注意要点 15 1.3.4 RS-422与RS-485的接地问题 16 1.4 IEEE 1284 1994并口标准 17 1.4.1 并行打印机端口概述 17
程序员进价应该注意的要点,编程的方法,技巧,以及学习心得。
3、计算常量dx,dy,2dy和2dy-2dx,并得到决策参数的第一个值: d0 = 2dy-dx 4、从k=0开始,在沿线路径的每个xk处,进行下列检测: 如果dk,下一个要绘制的点是(xk+1,yk),并且 dk+1 = dk+2dy 否则,下一个...
11.3.3 rs-422与rs-485的网络安装注意要点 317 11.3.4 rs-232、rs422、rs485电气参数对比 318 11.4 串口调试注意事项 318 11.5 常用数据校验法 318 11.5.1 奇偶校验 318 11.5.2 循环冗余码校验 319 11.6 串口...