c++基础(const关键词, 命名空间, 引用, 内联函数)
blog: http://withas.me
正好这学期在学c++, 打算把自己学习的都记录一下.
这篇文章主要是c++中的一些不同于c的特性.
const关键词
const通常用来表示常量,主要有以下一些用法:
符号常量
const type V = value表示V是一个常量.
在c语言中常量可以用宏定义, 如
#define PI 3.14. 这种方式在编译时把代码中的
PI全都替换为
3.14, 就是说
PI这个常量是没有被保存在内存中的. 而用
cosnt定义的变量会保存在内存的常量区.
修饰函数形参
用cosnt修饰的形参在函数指向过程中不能被修改.
int func(const int a) { // a++;//error return a + 5; }
当一个函数的功能明确不能或者不需要修改参数时可以用
cosnt修饰该参数.
修饰指针变量
const修饰指针变量有以下三种情况:
指向常量的指针
指向常量的指针, 也可以指向变量, 但是指针认为它指向了常量, 所以不能通过指针修改.
cosnt int a = 10; int b = 11; const int *p_a = &a;//a是常量 const int *p_b = &b;//ok, 指向常量的指针也能指向变量 // *p_a = 5;//error // *p_b = 6;//error虽然指向变量, 但是不能通过指针修改
常指针
指针变量是个常量, 必须初始化. 不能指向常量(常量只能被指向常量的指针指向), 可以通过指针修改. 其实就相当于一个普通指针, 但是赋初值后不能修改指向的地址.
// int *const p = &a;//error // 不能指向常量 int *const p = &b; *p = 20;//ok // p = &a;//error // 不能被修改
类中的this指针就是个常指针, 只能指向当前对象.
指向常量的常指针
只能指向常量, 而且本身是个常量, 是前两者的结合体.
// c 指向常量的常指针 什么都不能改 const int *const p_c = &a;
命名空间(namespace)
namespace可以用来区别不同文件里的相同名称的函数, 变量等.
namespace first_space { int a = 10; int func(const int a); // 嵌套namespace namespace second_space { int b = 11; } } //不连续命名空间 namespace first_space { // int a = 10;//error int b = 12; } //对命名空间中函数的实现 int first_space::func(const int a) { return a + 10; }
要使用命名空间中的成员, 需要使用
::运算符, 如
first_space::a.
可以用
using namespace space_name;来表示使用的命名空间, 这样可以省略命名空间, 比如要使用c++的标准库, 一般会
using namespace std;.
引用(reference)
引用相当于给变量取个别名.
int e = 10; int &f = e; cout << e << endl; f = 11; cout << e << endl;
这里
f相当于是
e的一个别名, 修改两者中的任何一个, 另一个会跟着一起改变.
按引用传参
c++的默认传参方式是按值传参, 实参的值会被复制到形参中.
而按引用传参不会复制, 而是直接引用实参, 不过会给实参取一个别名.
void add_five(int &a) { a += 5; }
其实大多数编程语言都是默认都是按值调用(call by value), 比如对于java来说只有call by value, 而c++有两种参数传递方式: 按值调用(call by value), 按引用调用(call by reference).
指针传递
c++传递指针作为参数, 还是call by value
void func(int *p) { *p = 10;//通过指针可以修改指向的值 p = NULL;//但是调用处的指针变量不会因为p变成NULL也变成NULL //因为调用处把传递的指针的值复制一份给了p, 修改p不会改变原来指针的值 }
java call by reference?
java中的对象变量储存的是对象的应用, 那么把对象变量作为参数传递是call by reference吗? 事实上, 这还是call by value, 不过传递的是引用的备份, 类似于c/c++中传递指针.
public static void swap(Object a, Object b) {//doesn't work Object temp = a; a = b; b = a; } //call swap(a, b);
调用
swap函数处a, b的值并没有变化, 因为函数中只是a, b引用的备份, 并非调用处a, b. 而正真的call by reference 是可以改变调用处实参的值.
void swap(int &a, int &b) { int temp = a; a = b; b = a; } //call int a = 4, b = 5; swap(a, b); //a = 5, b =4
好像很多人都没有搞清楚call by reference, 事实上call by reference只存在少数编程语言中. 虽然有时它的应用会简化程序, 不过个人认为call by value更加符合程序设计原则(不负责任偏激的见解).
修饰函数返回值
这是个有点变态的操作, 暂时没有搞懂有什么神奇操作
int &fn(int &b) { return b; } //main int n = 9; fn(n) = 11; //此时n=11
是不是很变态, 我第一看到也一脸懵逼.
内联函数(inline)
内联函数, 这是一个很实用的特性. 内联函数并不会真的被调用, 简单来说就是把函数的语句直接复制到执行的地方执行, 但是又不是像宏无脑的替换. 对于一些经常调用的函数, 这样可以减少函数调用的开销.
inline int max(int a, int b) { return a > b ? a : b; } //main int a = 10, b = 20; int c = max(++a, --b); //c = 19
调用
max的地方语句会被这样替换:
++a; --b; int c = a > b ? a : b;
对比以下宏定义的方式:
#define max(a, b) ((a) > (b) ? (a) : (b)) //main int a = 10, b = 20; int c = max(++a, --b); //c = 18 //此处语句被替换为 int c = (++a) > (--b) ? (++a) : (--b); //所以最后结果为18阅读更多
- C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针
- c++基础知识(命名空间、输入输出流、重载、缺省、引用)
- c++ 基础知识(输入输出、namespace命名空间、引用、函数重载模版、内存管理)
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
- C++基础:什么是命名空间
- 【C++】C++基础:指针__引用__const
- 【c++基础】const、const指针、const引用
- c++基础学习 - 命名空间
- C++语言基础(1)-命名空间
- C++基础积累(1)using namespace potter 自定义命名空间和使用
- C++ 基础之 "引用形参" 和 "利用const引用避免复制" &
- C++基础学习2:命名空间
- C++基础学习笔记----第六课(const和引用的扩展、重载函数和C方式编译的深入)
- c++基础の引用、const
- c++基础:指针_引用_const
- C++的基础知识(八)--命名空间、结构体
- C/C++的区别(默认值、内联函数、函数重载、const、引用、参数、返回值)
- c++多线程基础2(命名空间 this_thread)
- C++学习笔记1(结构体,命名空间,标准输入输出,引用,函数,构造函数)
- C++ 引用和指针 const与#define #define与内联函数