Chinaunix首页 | 论坛 | 博客
  • 博客访问: 578442
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:50:12

/***************************************************************************/
以下《C++ Primer》中的看书笔记。其中,每隔两行为一个新的话题,即使使用线相连
作者:Leoyin
/***************************************************************************/

for (vector::iterator it = text.begin(); it != text.end(); it++)


typedef char* cstring;
extern const cstring cstr; ==? char* const cstr;


return_type operator op(parameter_list);


%当有操作数为负数时,余数的正负取决于机器。


static_cast(i), const_cast(i), dynamic_cast(i),reinterpret_cast(i);


选择顺序容器的一些准则(vector, deque, list)
随机访问一个容器vector > list;
已知存储元素个数vector > list;
不在容器的两端插入删除元素 list > vector;
在容器首部插入删除元素 deque > vector;


将数组声明为引用,则函数参数中,数组长度成为函数参数中的一部分
void put(int (&arr)[10]); 长度被保留,数组没有被降价为指针(即sizeof(arr) != 4)


函数指针的数组
int (*test[10])(int n);
等价于
typedef int (* PFN)(int n);
PFN test[10];
调用时
int ret = test[i](value)


int (*ff(int))(int*, int);
该声明将ff()声明为一个函数,它有一个int型的参数,返回一个指向函数的指针,返回类型为
int (*)(int*, int);
例如
int fun(int*, int)
{
    return 1;
}

int (*ff(int))(int*, int)
{
    return fun;
}


static变量仅在最初分配内存时被初始化值
int f1(int a)
{
    static int j = 1;   //仅被初始化一次!
    return j++;
}


char* p = new char;
if (p != 0) //不需要检查,这样实际检查了两次,这里一次,delete 的时候(调用delete())一次
    delete p;
假如 char *p = 0;
delete p 不会起到作用的,所以在delete p 的时候,最好p = 0;这样可以不用 if(p != 0)...


const int *p = new const int[10];//错误,不可以创建内建类型的const数组,因为const需要初始值,
                                                //而内建类型的数组无法初始化


定位new表达式(placement new expression)
#include
class Foo{};
char* buf = new char[sizeof(Foo) * 10];
Foo* pb = new(buf)Foo; //在buf中创建一个Foo对象
delete[] buf; //因为buf才是真正开辟的heap,pb只是分配在buf上。pb需要pb->~Foo();显示调用


域操作符(::)也可被用来引用全局名字空间的成员,因为全局名字空间没有名字所以
::g_member 指向全局名字空间成员。所以可以通过该方法引用如下:
void func()
{
    int g_member;
    g_member = ::g_member; //引用全局的g_member变量
}


嵌套名字空间
namespace A
{
    namespace A1
    {
        void func();
    }

    namespace A2
    {
        void func();
    }
}
使用
A::A1::func();     //A1域中的
A::A2::func();     //A2域中的

非inline 函数和对象在程序中只能被定义一次,同样适用于namespace

未命名的名字空间定义于一个局部的特定的文件,不能跨越多个文件
namespace { void func(){} } //未命名的名字空间,引用时直接引用func();
该定义如同使用static void func()

const, volatile应用在按值传递的函数的时候,则不视为函数重载(function overloading)
void func(int )
void func(const int)
视为同一函数,因为是按值传递的(即复制传递的参数)
而对于应用到指针或引用的参数时,视为函数重载
void func(int*);      void func(const int*);
以及
void func(int&);     void func(const int&);
视为函数重载


extern "C" 只能应用于一个重载的函数上,对于C,C++的调用则分别选择相应的调用


指向重载函数的指针,会选择与该指针匹配的重载函数(包括返回值也要相同,函数指针的特点)
void ff(int);         void ff(double);
void (*f)(int) = &ff; // or = ff; 选择的是void ff(int);


用函数实参的类型来决定模板实参的类型和值的过程被称为函数实参推演
(template argument deduction)


以下这个引自《C++ Primer》13.5 静态类成员,但是并不可以编译通过
.h 中:
class A
{
private:
    static const int size = 16; //因为下面用到size,所以要提前给出初值,但是VC中并不能编译
    static const char name[size];
};
.cpp 中:
const int A::size; //这个定义是必需的!                                              <-------------------------------------------|
const char name[size] = "some...";                                                                                                                          |
                                                                                                                                                                              |
                                                                                                                                                                              |
                                                                                                                                                                              |
静态数据成员,可以在该类中的任何成员函数中调用及初始化,但是必须要给出该变量的定义.如:--
静态成员函数(staitc void func(){})只能调用该类内部的static 类型的数据成员。
调用static类型的数据成员以及成员函数可以采用如下:
class A
{
public:
    staitc void func();
    static int i;
};

A a;
a.i;                     a.func();                    A::i;               A::func();
都是正确的。

 

class A
{
public:
    int m_param;
    static int m_sparam;
    void func(){};
    static void func(int a){};
};
int A::m_sparam = 0; //一定要给出定义

int A::* pa = &A::m_param;      //非static
int *pb = &A::m_sparam;         //static类型
void (A::* pA)() = &A::func;    //非static类型
void (* pB)(int) = &A::func;     //static类型
//非static类型的指针引用一定要明确表明是哪个类的,因为含有this指针
调用时:
A a, *p;
(a.*pA)();
(p->*pA)();
a.*pa;
p->*pa;
以上引用类的非static函数指针多被用于在类中的回调函数,例如:
typedef A&(A::*Action)();
A& A::Repeat(Action op) //调用的时候可以 op = &A::func
{
    for(int i = 0; i??(this->*op)();
    return *this;
}
这样对于一个对象的非static类型的成员函数,也可以作为回调函数传入,而不用因为类的
static变量的改变,而影响整个类的所有对象

   

union 类型可以像使用class一样,定义成员函数即变量,默认为public。但是变量只能有一个
为当前使用的,也就是所有变量共享一段存储区,存储区大小为所有变量中长度最大的。
一般经常使用的是匿名union,如union{}; "{}"前后不包含名称,这样它可以不用使用. ->操作符
来引用,也就是去掉了一层成员访问操作符。


class A
{
    typedef int money;
private:
    static money m_sParam;
};
//对于用typedef定义的类型,在类体外时一定要明确的指定类的域A::
A::money A::m_sParam = 1;

   

任何类型的const和引用数据成员 必须在成员初始化列表中被初始化
class A
{
public:
    A(int a, int b);
    const int i;
    int &j;
};
A::A(int a, int b) : i(a), j(b) {}
而初始化的顺序是变量i,j在类中的声明顺序决定的

  

效率考虑:(伪代码)
Point3d p3;
p3 = operator+(p1,p2);
可能被转化为
Point3d temp;??? //临时对象
operator+(temp, p1, p2); //对于返回一个类对象,编译器内部翻译成这种样子,
p3.Point3d::operator=(temp); //按成员赋值
temp.Point3d::~Point3d();?? //析构掉临时对象。所以这些开销很大,而且还会造成错误!
所以 Pointed p3 = operator+(p1,p2);效率更高

 


--------------------next---------------------

阅读(293) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~