(1) 被extern "C"限定的函数或变量是extern类型的
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:
extern int a;
仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
(2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的
2、explicit构造函数的作用
explicit构造函数是用来防止隐式转换的。请看下面的代码:
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1=12;//隐式调用其构造函数,成功
Test2 t2=12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
Test1的构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。
3、auto_ptr智能指针
std::auto_ptr是C++标准库里面的模版类, 属于智能指针当系统异常退出的时候避免资源泄漏(内存)。 其他的资源还对应其他的智能指针。
(2)、 auto_ptr的使用
std::auto_ptr<int> test(new int(1));
test将是一个auto_ptr的对象,使用一个int指针进行初始化。
test可以象其他指针一样使用,如使用* 使用->但是++不可以使用,以后也许会扩展,其实难对++做越界管理,也许可以放弃一些速度。
当使用auto_ptr的时候,必须使用显式的类型转化来初始化,如auto_ptr<classA> a(new classA)
而不能使用auto_ptr<classA> a = new classA;
(3)、auto_ptr所有权的转移
auto_ptr对所有权有严格的约定,一个auto_ptr只能控制一个指针,不能控制多个,当auto_ptr拥有一个指针的时候就不能在拥有其他的指针了。同时,不同的auto_ptr不能拥有同一个指针。
(1)尽量不要使用“operator=”(如果使用了,请不要再使用先前对象)。
(2)记住release()函数不会释放对象,仅仅归还所有权。
(3)std::auto_ptr最好不要当成参数传递(读者可以自行写代码确定为什么不能)。
(4)auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。
(5)auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。auto_ptr不能指向数组,因为auto_ptr在析构的时候只是调用delete,而数组应该要调用delete[]。
(7)auto_ptr不能共享所有权,即不要让两个auto_ptr指向同一个对象。
(8)auto_ptr不能作为容器对象,STL容器中的元素经常要支持拷贝,赋值等操作,在这过程中auto_ptr会传递所有权,那么source与sink元素之间就不等价了。
4、构造函数的初始化列表
函数模板的实例化是由编译程序在处理函数调用时自动完成的
类模板的实例化必须由程序员在程序中显式地指定函数模板针对仅参数类型不同的函数类模板针对仅数据成员和成员函数类型不同的类6、类的静态成员和非静态成员
(1)、数据成员可以分静态变量、非静态变量两种. 静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.静态成员在每个类中只有一个拷贝,是解决同一个类的不同对象之间数据和函数共享问题的。 非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中.一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..
静态成员函数可以直接引用该类的静态数据成员和静态成员函数,但不能直接引用非静态数据成员和非静态成员函数,否则编译报错。如果要引用,必须通过参数传递的方式得到对象名,然后再通过对象名引用(2)、
区别:访问方式不一样.静态成员(通过类名.静态成员名访问).非静态成员(通过对象名.非静态成员名访问)静态成员属于类.该类的所有对象共同拥有这一个成员.非静态成员属于对象,每个对象都有一份.静态成员不论有类有多少个对象.只在内存中分配一块空间.7、运算符
& 按位与运算,如:1010 & 1100 = 1000
| 按位或运算,如:1010 & 1100 = 1110
~ 非运算,如:a = 1010; ~a = 0101
<<左移,如:1110 << 1 = 1100
>>右移,如:1000 >> 1 = 0100
8、递归#include <stdio.h>
int
cnt=0;
int
fib(
int
n){
cnt++;
if
(n==0)
return
1;
else
if
(n==1)
return
2;
else
return
fib(n-1)+fib(n-2);
}
void
main()
{
fib(8);
printf
(
"%d"
,cnt);
==》67}
9、C89支持无返回类型的函数,默认返回int型C99开始必须要有返回值
可重载的操作符
输入和输出操作符;算术操作符;关系操作符; 赋值操作符和符合赋值操作符;下标操作符;成员访问操作符;引用操作符(*)和箭头操作符(->);自增操作符和自减操作符;调用操作符和函数对象
其实除了上面说的,还有很多可重载:
逻辑操作
位操作符;
new/delete操作;
而不可操作的操作符比较少,可直接列出来:
作用域操作符:::
条件操作符:?:
点操作符:.
指向成员操作的指针操作符:->*,.*
预处理符号:#