extern关键字
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。通常用于当有两个或多个文件共享相同的全局变量或函数。
// 文件1
#include <iostream>
int count ;
extern void write_extern();
int main(){count = 5; write_extern();
}// 文件2
#include <iostream>
extern int count;
void write_extern(void){std::cout << "Count is " << count << std::endl
}
sizeof
返回变量内存占用的大小,单位为字节。
int a = 10;
sizeof(a); // int 4个字节
指针运算符&
和*
&
返回变量的地址。例如&a;
将给出变量的实际地址。
*
指向一个变量。例如*var;
将指向变量 var。
举个例子:
int a = 10;
int* p = &a;
cout << "value of a = " << a << endl; // 10
// 输出在指针变量中存储的地址
cout << "value of p = " << p << endl; // 0x7ff7ba1fb368
// 访问指针中地址的值
cout << "value of *p = " << *p << endl; // 10int** pp = &p;
cout << "value of pp = " << pp << endl; // 0x7ff7bf660360
cout << "value of *pp = " << *pp << endl; // 0x7ff7bf660368
可以看到*p = a
,*pp = p
。
c++引用和指针
是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
// 声明简单的变量
int i = 5;
// 声明引用变量
int& r = i;
函数参数
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
c++中函数参数默认是传值调用!
Lambda函数和表达式
C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。Lambda 表达式把函数看作对象。
基本语法:
[capture](parameters)->return-type{body}
在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。
[] // 沒有定义任何变量。使用未定义变量会引发错误。
[x, &y] // x以传值方式传入(默认),y以引用方式传入。
[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。
c++中c风格字符串
C 风格的字符串实际上是使用 null 字符 '\0'
终止的一维字符数组。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char greeting[] = "Hello";
c++运算符重载
比如:
Timer operator+(const Timer& t);
Timer operator==(const Timer&, const Timer&);
虚函数
虚函数 是在基类中使用关键字 virtual
声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
举个例子
class Shape {
protected:int width, height;
public:Shape(int a = 0, int b = 0) {width = a;height = b;}void area() {cout << "Parent class area : NOTHING" << endl;}
};class Rectangle : public Shape {
public:Rectangle(int a = 0, int b = 0) : Shape(a, b) {}void area() {cout << "Rectangle class area :" << width * height << endl;}
};class Triangle : public Shape {
public:Triangle(int a = 0, int b = 0) : Shape(a, b) {}void area() {cout << "Triangle class area :" << width * height / 2 << endl;}
};
然后我们在调用的时候:
Shape* shape = new Rectangle(2, 3);
shape->area(); // NOTHING
Triangle triangle(2, 3);
shape = ▵
shape->area(); // NOTHING
造成这样的问题,就是因为调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态链接。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
解决上边这个问题,加上virtual
关键字:
virtual void area() {cout << "Parent class area : NOTHING" << endl;
}
另外我们上边在Shape中定义的area()
函数完全没有意义,具体都由其子类去实现,那么这个时候,可以将其定义为纯虚函数:
virtual void area() = 0;
c++ 动态内存
在 C++ 中,可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。这种运算符即new
运算符。
如果您不需要动态分配内存,可以使用delete
运算符,删除之前由new
运算符分配的内存。
int* p = new int;
*p = 1;
cout << "value of p = " << *p << endl;
delete p;char* array = new char[1];
array[0] = 'a';
cout << "value of array = " << array << endl;
delete [] array;
函数模板和类模板
函数模板
模板函数定义的一般形式如下所示:
template <class type> ret-type func-name(parameter list){ // 函数的主体
}
在这里,type 是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用。
比如一个返回比较大小值的函数:
template<typename T>
inline T const &Max(T const &a, T const &b) {return a < b ? b : a;
}
类模板
泛型类声明的一般形式如下所示:
template <class type> class class-name {...}
在这里,type 是占位符类型名称,可以在类被实例化的时候进行指定。您可以使用一个逗号分隔的列表来定义多个泛型数据类型。
多线程
Linux POSIX
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) //创建线程
pthread_exit (status) // 退出线程
pthread_join(pthread_t , status) // 用于等待指定的线程终止,会阻塞调用它的线程
pthread_detach (threadid) // 用于将指定的线程标记为"可分离的",以便在线程终止时自动释放其资源
看一个例子:
void *thread_function(void *arg) {int *value = (int *)arg;int *result = new int;*result = *value + 5;pthread_exit(result);
}int main() {pthread_t thread;int value = 10;void *thread_result;pthread_create(&thread, NULL, thread_function, (void *)&value);pthread_join(thread, &thread_result);int* result = (int*)thread_result;printf("Thread returned: %d\n", *result);delete result;return 0;
}