C++入门必备

  1. 使用cout标准输入和cin标准输出时,必须包含的头文件和std的标准命名空间。
#include <iostream>
using namespace std;
int main ( ){
  int a;
  cin >> a;
  cout << "hello" << endl;//endl的实际意义是换行
  //cout << "hello\n";
  return 0;
 }
  1. 命名空间:用namespace加上命名空间的名字,后面跟一对{ },里面放上命名空间的成员。其目的就是对标识符的名称进行本地化,以避免命名冲突或名字污染。命名空间既可以定义变量,也可以定义函数,还可以嵌套使用。
#include <iostream>
uaing namespace std;

namespace GXR
{
  int N = 10;//
  int Add (int x,int y){
     return x+y;
   }
  namespace B {
   int N3 = 30;
  }
}
//直接使用命名空间名称加作用域限定符来表示:
int main ( ){
  cout << GXR::N << endl;
  cout << GXR::B::N3 << endl;
  return 0;
}
//或者是事先使用using将命名空间中成员引入:
using namespace GXR;
int main ( ){
  printf ("%d ",Add(1,3));
  return 0;
}

注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

  1. 缺省参数:声明或定义函数时为函数的参数指定一个默认值。在调用该函数的时候,如果没有指定实参则采用该默认值,否则使用指定的实参。
    分为全缺省参数和半缺省参数。
#include <iostream>
using namespace std;
//全缺省:
void func (int a = 2,int b = 3){
  cout << a << endl;
  cout << b << endl;
 }
int main ( ){
  func( );   //结果为:2 3
  func(1);   //       1 3
  func(1,1); //       1 1
  return 0;
}
//半缺省:**只能从右向左**依次**缺省**。
void func (int a, int b=3,int c=6){
  cout << a << endl;
  cout << b << endl;
  cout << c << endl;
}
int main ( ){
 func(1);       //结果为:1  3  6
 func(1,1);     //       1  1  6
 func(1,1,1);   //       1  1  1
 return 0;
}

注意:半缺省只能从右向左依次缺省,缺省参数不能在声明和定义中同时出现,缺省值必须是常量或者是全局变量。

  1. 函数重载:C++允许在同一作用域中声明几个功能类似的同名函数,但是它们的形参列表(即,参数个数 或 类型 或 顺序)必须不同。
int Add (int a, int b){
  return a+b;
}
double Add (double a, double b){
  return a+b;
}

以上两个函数就可以构成函数重载。
原因分析:编译器实际在底层使用的不是Add名字,而是被重新修饰过的一个比较复杂的名字,其中被重新修饰后的名字中包含:函数的名字以及参数类型
这就是为什么函数重载中几个同名函数要求其参数列表不同的原因,只要参数列表不同,编译器在编译时通过对函数名字进行重新修饰,将参数类型包含在最终的名字中,就可保证名字在底层的全局唯一性。(利用了C++的函数名修饰规则)
如:上面代码所展现的函数名分别可以表示为:_Z3Addii. 和 _Z3Adddd.

关于C语言中为什么不能支持函数重载?
原因:C语言的名字修饰规则非常简单,只是在函数名字前面添加了下划线。因此 当工程中存在相同函数名的函数时,就会产生冲突。
C++中函数重载的底层是怎么处理的?
编译器在底层使用的不是Add名字,而是被重新修饰过的一个比较复杂的名字,包括函数的名字和参数的类型。

  1. 引用:不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它所引用的变量共用同一块内存空间
#include <iostream>
using namespace std;
//正确的引用:
int main ( ){
 int a = 10;
 int&b = a;// 引用在定义时必须初始化
 int&c = a;// 一个变量可以有多个引用
}
//错误的引用:
int main ( ){
 int a = 10;
 int m = 20;
 int&b = a;
 int&b = m;//引用一旦引用一个实体,再不能引用其他实体
}

注意:引用在定义时必须初始;一个变量可以有多个引用;一旦引用一个实体就不能在引用另外一个实体。
引用类型必须和引用实体的类型相同
常引用必须也要和实体保持一致,加const修饰:
如: const int a = 12; ------------const int& b = a;

#include <iostream>
using namespace std;
void Swap (int& x,int& y){
 int tmp = x;
 x = y;
 y = tmp;
}
int main ( ){
 int x = 12;
 int y = 13;
 Swap(x,y);
 cout << x << endl;
 cout << y << endl;
 return 0;
}
#include <iostream>
using namespace std;
int& func (int& a){
  a += 10;
  return a;
}
int main ( ){
  int a = 20;
  cout << func(a) << endl;
  return 0;
 }

上述两个代码说明了,引用可做参数,以此来减少拷贝,提高效率;
引用也可做返回值,但是注意:当返回对象是局部变量时,不能用引用返回;当法返回对象出了当前的作用域,依旧存在时,可以用引用返回。

Struct A
{
  int a[10000];
};
A a;
void Test1(A a){ };
void Test2(&A a){ }//对引用传参效率的检验
Struct B
{
  int b[10000];
};
B Test3( )
{  return a;}
&B  Test4( )
{  return a;}
//对引用传返回值效率的检验
void TestTime ( ){
  size_t begin1 = clock( );
  for( size_t i=0; i<10000; i++){
    Test1( );
   }
  size_t end1 = clock( );
  size_t begin2 = clock( );
  for( size_t i=0; i<10000; i++){
    Test2( );
   }
  size_t end2 = clock( );
  cout << end1-begin1 << endl;
  cout << end2-begin2 << endl;
 }
 int main ( ){
   TestTime( );
   return 0l
 }

传引用返回和普通的传返回值相比,传引用返回的效率更高;
传引用参数和普通的传参相比,传引用参数的效率更高。

引用和指针的比较:
1、引用必须初始化。
2、没有空引用。
3、引用一个实体后,就不能再引用其它的实体;指针可以在任何时候指向任何一个同类型的实体。
4、在sizeof中,引用的结果是类型的大小;指针的结果是地址的大小
5、引用自增,加的是引用的实体值加1;指针自增,加的是类型的大小
6、访问实体方式不同,指针需要显式解引用,引用是依靠编译器自己处理。
7、有多级指针,但是没有多级引用,引用比指针使用起来相对更安全。

  1. 宏和内联函数:
#define ADD(a,b) ((a)+(b))
int main ( ){
  int c = ADD(1,2);
  printf ("%d ",c);
  return 0;
}

宏函数中不需要参数类型,在预处理的时候被替换。
优点:增强代码重用性,提高性能。
缺点:不能调试宏,可读性、可维护性差,没有类型安全的检查。

#include <iostream>
using namespace std;
inline void func(int i);
void func (int i){
  cout << i << endl;
 }
int main ( ){
  func(20);
  return 0;
}

内联函数是一个以空间换时间的做法,不用写重复的代码,避免了函数内部的压栈。
注意:不建议inline的声明与定义分离,分离会导致连接错误;不适合太长的代码,对编译器而言inline只是一个建议,编译器会自动优化。

总结宏和内联函数:C++中,常量用const修饰,在函数中,用inline来替换宏。

  1. 感受auto:
    使用auto定义变量时必须对其进行初始化,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。
#include <iostream>
using namespace std;
int main ( ){
 int a = 12;
 auto b = &a;
 auto*c = &a;
 auto&d = a;
 cout << typeid(b).name( ) << endl;   //int*
 cout << typeid(c).name( ) << endl;   //int*
 cout << typeid(d).name( ) << endl;   //int 
 return 0;
}

(typeid ( 变量名称).name( )): 用来在运行时获知变量类型名称
用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明 引用类型时则必须加**&**。

  1. 范围for:用于在C++中,遍历一个数组。
#include <iostream>
using namespace std;
int main ( ){
 int a[6] = {1,2,3,5,7,9};
 for (int i=0; i<sizeof(a)/sizeof(a[0]); i++){
   cout << a[i] << endl;
  }

 for (auto e:a){
  cout << e << endl;
  }
 //让数组的值扩大2倍
 for (auto e:a){
  cout << e*2 << endl;
 }
 //让数组的值扩大2倍(利用引用)
 for (auto& e:a){
  cout << e*2 << endl;
 }
 return 0;
}

在C++中,由于NULL被定义成0,所以C++ 中用nullptr来代替NULL。

猜你喜欢

转载自blog.csdn.net/Darling_sheeps/article/details/86481142