函数必须先被声明,之后才能被引用/调用,声明不必提供函数体,但必须指明返回类型、函数名、参数列表。
int fibon_elem(int pos);
//
bool fibon_elem(int pos, int &elem);
//
bool fibon_elem(int, int &);
//目的只是让编译器知道这个函数的存在
终止整个程序的时候,可以使用exit()这个函数。而在cstdlib这个头文件当中,就包含了这个函数。
想知道某个类型中的最大最小值时,可以查询limits class。
#include
int max_int = numeric_limits<int>::max();
double min_db1 = numeric_limits<double>::min();
Vector是一种数组,既然是一种数组,那么肯定有普通数组的一系列特性,比如可以通过下标对数组当中的元素进行引用。Vector也是一种可以存放任意动态类型的数组。综上,称之为容器。
vector<int> vec(1,2,3);
//
vector<int> vec(a);
//a这个向量给vector初始化
int ia[8] = {1,2,3,4,5,6,7,8};
vector<int> vec(ia, ia+8);
//以上这两行操作是把ia当中的元素来给vector进行初始化
vector<int> vec(&m[0], &m[10]);
//将m[0]~m[10]范围内的元素给vector进行初始化
//vector的基本操作
vec.push_back(i) ;
//在尾部插入i
vec.insert(vec.begin(),i);
//在第一个元素之前插入i
vec.assign(5,1);
//插入5个1
vec.pop_back();
//相当于pop出栈
vec.erase(vec.begin());
//删除第一个元素的数值
vec.clear();
//
vec.empty();
//
//遍历vec
vector<int> vec;
for(int i=0;i<vec.size();++i){
cout << vec[i];
}
//利用迭代器进行访问
vector<int>::iterator iter;
for(iter=vec.begin();iter!=vec.end();iter++){
cout << *iter;
}
//建立二维数组
cin >> n >> m
vector<vector<int>>vec(n);
for(int i=0;i<n;++i){
vec[i].resize(m);
}
例如有一个swap函数
void swap(int val1, int val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
在主函数当中,swap被调用之后,其实从vector当中传给swap()函数的对象被复制了一份(vector中的对象传入函数当中是会被默认复制一份的,成为参数的局部性定义),原对象与副本之间是没有任何关联的。
令swap()的参数和传入的实际对象产生关联,这就是所谓的传址,把真正的地址给传进去,就能把真实值给改变。
void swap(int &val1, int &val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
所以,要真正改变vector当中对象的数值时,要使用传址而不是传值。
对象在程序内的存活区域成为对象的scope(作用域)。
对象如果在函数以外声明,具有所谓的file scope,相当于全局变量。
local scope之内的,相当于局部变量,需指定参数,否则不会被初始化。
local scope与file scope,都是系统自动分配空间的。
分配:new
释放:delete
int *pi;
pi = new int;
//
delete pi;
局部对象的地址返回会出现错误,但是有一个例外(指的是static)。
局部静态对象所处的内存空间,即使在不同的函数调用过程当中,依然持续存在。
全局对象 std::cerr 和 std::wcerr 控制到实现定义类型(分别导出自 std::streambuf 和 std::wstreambuf )的流缓冲,与标准 C 错误输出流 stderr 关联。
将之前分散开来的各个独立的函数,整合进一个函数内,但任然保持n个独立的运算单元,这就是inline function,只需在头文件处加上inline即可。
C++特性,参数列表不想同的两个或者多个函数,可以拥有相同的函数名称,这就是函数的重载。需要注意的是不能通过返回的类型来区分两个不同函数的语境。
int sum(int x, int y)
{
cout << "sum(int, int) is called" << endl;
return x + y;
}
float sum(float x, float y)
{
cout << "sum(float, float) is called" << endl;
return x + y;
}
double sum(double x, double y)
{
cout << "sum(double, double) is called" << endl;
return x + y;
}
template <typename elemType>
void display_message(const string &msg, const vector<elemType> &vec)
{
.......
}
此处的关键字typename以及elemtype只是占位符。当指定了vector的数据类型时,elemType才会绑定相应的类型。
这个模板既可以是函数模板也可以是参数模板。template本身也可以做类型,相当于套娃。
函数模板的 其中的elemType要与之后的elemType开头相同。
template<typename T>
T sum(T x, T y)
{
cout << "The input type is " << typeid(T).name() << endl;
return x + y;
}
编译器看到这个函数时,编译器不知道怎么做,因为不知道类型。要调用函数模板的话,就得进行实例化。
template double sum<double>(double, double);
//一种更简化的类型就是下面
template int sum(int, int);
template<typename T>
T sum(T x, T y)
{
cout << "The input type is " << typeid(T).name() << endl;
return x +
y;
}
// Explicitly instantiate
template double sum<double>(double, double);
int main()
{
auto val = sum(4.1, 5.2);
//auto就是返回值是什么类型,这个val就是什么类型
cout << val << endl;
return 0;
}
在实例化当中进行类型的赋值就行,实例化之后直接在main函数当中调用这个函数就行。
注意,模板的调用分显式的实例化还有隐式的实例化,就是不一定非要把实例化写出来。
template<typename T>
T sum(T x, T y)
{
cout << "The input type is " << typeid(T).name() << endl;
return x + y;
}
int main()
{
// Implicitly instantiates product(int, int)
cout << "sum = " << sum<int>(2.2f, 3.0f) << endl;
// Implicitly instantiates product(float, float)
cout << "sum = " << sum(2.2f, 3.0f) << endl;
return 0;
}
结构体也可以是一个类型,不过其实例化是一个特例化,要加上一个尖括号<>。
普通的实例化如下
template
double sum<double>(double, double);
//特例化如下
template<>
Point sum<Point>(Point pt1, Point pt2);
//Point代表结构体类型
必须指明所指函数的返回类型以及参数列表,以及赋予一个名称。
const vector<int>* (*seq_ptr)(int);
在这,参数列表内容为int,返回类型为const vector*。
若要显示循环,在每次迭代过程中将seq_ptr设置为各个不同的数列函数,可以利用数组索引的技巧。
const vector<int> * (*seq_array[])(int) = {
fibon_seq, lucas_seq.........
};
尖括号就是从编译器指定的include路径去找头文件,双引号就是从不光从编译器指定的路径找,而且还从当前这个cpp文件的当前目录去找。