C/C++基础知识
栈上分配内存: alloca()
The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is
automatically freed when the function that called alloca() returns to its caller.
automatically freed when the function that called alloca() returns to its caller.
作用域
extern也可以在函数声明中指定,唯一的影响是将该声明的隐式属性“在其它地方定义”变为显示。
extern void putValue(int *, int);
register声明寄存器自动对象,适合函数中频繁被使用的自动变量,比如循环语句中的数组索引和指针;register对编译器来说只是一个建议,编译器使用寄存器分配算法找出最合适的候选放到机器可用的寄存器中。
静态局部对象,static,它的值在函数调用之间保持有效,但其名字的可视性仍限制在其局部域内;在对象的声明处被首次初始化
const
指向const对象的指针: const double *ptr;
1. 其本身不是常量,可以重新赋值,使其指向不同的对象,但不能修改其指向的对象;
2. 指向const对象的指针可以被赋以一个非const对象的地址;
3. 常被用作函数的形式参数;
const指针:int *const ptr2 = #
1. ptr2是指向非const对象的const指针,
auto_ptr
auto_ptr对象被初始化为指向由new表达式创建的动态分配对象,当auto_ptr对象的生命期结束时,动态分配的对象被自动释放。
auto_ptr<string> pstr_auto( new string("break point") );
if ( pstr_auto->empty() ) {
}
auto_ptr不能用于数组
auto_ptr.get() 返回内部底层指针
auto_ptr.reset() 设置内部底层指针
auto_ptr.release() 释放底层对象的所有权,并返回对象地址
placement new expression
定位new表达式,将对象创建在已经被分配好的内存中。
char *buf = new char[ sizeof(Foo) * chunk ];
Foo *pb = new (buf) Foo; // 在buf中创建一个Foo对象;
unnamed namespace
未命名名字空间,声明一个局部于某一文件的实体,只在该文件中可见,在其他文件中不可见。
类似于C语言中使用static来限制全局实体只在声明它的文件中可见。
namespace {
void swap( double *d1, double *d2 );
}
静态类成员
静态数据成员一般在该类定义之外被初始化,并且应该放在含有类的非inline函数定义的文件中,而不是头文件中;否则编译时会导致“重定义”错误,如果头文件被多次引用的话。
#include "account.h"
double Account::interestRate = 0.0589;
有序型的const静态数据成员可以在类体中用常量值初始化;同时,该成员必须仍然要被定义在类定义之外,但不能指定初始值。
class Account {
static const int nameSize = 16;
}
const int Accout::nameSize; // 必须的成员定义
template
模板参数分为:类型参数 与 非类型参数(常量表达式)
模板类型参数由关键词class或typename后加一个标识符构成:
template<class Type, int size>
Type min( Type (&arr)[size] );
函数模板在被调用或取其地址时被实例化:
int (*pf) ( int (&)[10] ) = &min;
iterator适配器
typeid和type_info
typeid用于获取一个表达式的类型,其返回type_info的类对象;
如果表达式是一个类类型,并且含有一个或多个虚拟成员函数,则typeid会指出底层对象的派生类类型;
如果不是带有虚拟函数的类类型时,typeid会指出操作数的类型,而不是底层对象的类型;
programmer pobj;
employee &re = pobj;
cout << typeid( re ).name() << endl; // "programmer"
dynamic_cast
dynamic_cast用来执行从基类指针到派生类指针的安全转换,称为安全的向下转换;
当必须使用派生类的特性,而该特性又没有出现在基类中时,就需要使用dynamic_cast;
void company::payroll( employee *pe ) {
if ( programmer *pm = dynamic_cast<programmer *>(pe) ) {
// 使用pm调用programmer::bonus()
}
else {
// 使用employee的成员函数
}
}
dynamic_cast也可以用来把一个基类类型的左值转换成派生类类型;
多态
C++以下面3种方式支持多态性:
1. 通过一个隐式转换,从“派生类指针或引用”转换到“其公有基类类型的指针和引用”;
2. 通过虚拟函数机制:pquery->eval();
3. 通过dynamic_cast和typeid操作符:if ( NameQuery *pnq = dynamic_cast<NameQuery *>(pquery) )
迭代器、mutable、volatile
static
//----------------------------------------------------------------------------
// 编译器指令
//----------------------------------------------------------------------------
编译器指令:error
#if defined(HAVE_SDL_IMAGE_H)
#include <SDL/SDL.h>
#elif defined(HAVE_IMLIB2_H)
#include <Imlib2.h>
#elif defined(HAVE_CV_H)
#include <cv.h>
#include <highgui.h>
#else
#error "No imaging library"
#endif
#include <SDL/SDL.h>
#elif defined(HAVE_IMLIB2_H)
#include <Imlib2.h>
#elif defined(HAVE_CV_H)
#include <cv.h>
#include <highgui.h>
#else
#error "No imaging library"
#endif
#define GNUC_PRINTF(format_idx, arg_idx)
告诉编译器format和args的位置
void purple_debug(PurpleDebugLevel level, const char *category,const char *format, ...) G_GNUC_PRINTF(3, 4);
//----------------------------------------------------------------------------
// G++链接GCC编译的目标文件
//----------------------------------------------------------------------------
如果C++程序需要使用C写的程序,则需要在C程序的头文件里面使用extern "C"将类型和函数声明封装起来
#ifdef __cplusplus
extern "C" {
#endif
extern "C" {
#endif
/* declarations */
#ifdef __cplusplus
}
#endif
}
#endif
//----------------------------------------------------------------------------
// va_list
//----------------------------------------------------------------------------
[ Header ]
#include <cstdarg>
#include <cstdarg>
[ 一般的用法 ]
va_list args; //声明变量
va_start(args, format); //开始解析, args指向format后面的参数
TYPE var = va_arg(args, TYPE); //取下一个参数并返回。args指向下一个参数
va_end(args); //结束解析
[ 例子 ]
1. long Slog::write( const int log2tty, const char *format, ... )
{
va_list args;
char msg[1024];
va_start(args, format);
vsnprintf(msg, 1024, format, args);
msg[1023] = 0; // ensure not overflow
va_end(args);
2. 求若干个整数的平均值
#include
int AveInt(int,...);
void main()
{
printf("%d\t",AveInt(2,2,3));
printf("%d\t",AveInt(4,2,4,6,8));
return;
}
}
int AveInt(int num,...)
{
int ReturnValue=0;
int i = num;
va_list myvalist;
va_start(myvalist,num);
while(i>0)
{
ReturnValue += va_arg(myvalist,int);
i--;
}
{
ReturnValue += va_arg(myvalist,int);
i--;
}
return ReturnValue/=num;
}
}