乐趣区

关于c++:C入门

命名空间 namespace

  • namespace:命名空间,相当于定义了一个作用域,用来解决命名抵触问题。
  • 域作用限定符:拜访命名空间中的内容,应用双冒号 : :,当: : 右边为空时,示意应用全局域。
// 定义第一个命名空间
namespace first_space{void func(){
       int a = 1;
      cout << "Inside first_space" << endl;
   }
}
// 定义第二个命名空间
namespace second_space{void func(){
       int a = 2;
      cout << "Inside second_space" << endl;
   }
}
int a = 10;
int main ()
{ 
    int a = 5;
    printf("%d\n",a);   //a = 5,就近准则,应用 a = 5 的那个。printf("%d\n",first_space::a);  //a = 1
    printf("%d\n",::a);  //a = 10,:: 右边为空,代表应用全局域(全局变量)// 调用第一个命名空间中的函数
   first_space::func();
   
   // 调用第二个命名空间中的函数
   second_space::func(); 
 
   return 0;
}
  • using:using namespace 指令,这个指令会通知编译器,后续的代码将应用指定的命名空间中的名称,这样在应用命名空间时就能够不必在后面加上命名空间的名称。
using namespace first_space;
int main ()
{
   // 调用第一个命名空间中的函数
   func();
   return 0;
}
  • 嵌套命名空间,能够应用: : 来拜访嵌套的命名空间。
namespace namespace_name1 {
   // 代码申明
   namespace namespace_name2 {// 代码申明}
}

// 拜访 namespace_name2 中的成员
using namespace namespace_name1::namespace_name2;
 
// 拜访 namespace_name1 中的成员
using namespace namespace_name1;
  • C++ 库为了避免命名抵触,将本人库中的货色都定义在一个 std 的命名空间中
  • 所以有时候程序中都会调用 using namespace std; 这个库。
#include <iostream>  // 援用.h 头文件,为了与老版辨别,在新版中不必写.h
using namespace std;  // 调用 std 库

int main()
{
    cout << "hello world" << endl; // 因为下面写了 using,所以能够不写命名空间
    std::cout << "hello world" << std::endl;  // 指定命名空间
    return 0;
}

C++ 输出和输入

  • C++ 的输入输出能够自动识别类型,不必手动表明。

    #include <iostream>
    using namespace std;
    
    int main()
    {
      int a = 10;
      cout << a << endl << "hellow world" << endl;  //cout 示意输入,endl 示意换行
      cin >> a ;    //cin 示意输出相当于 scanf,然而不必指定类型,会自动识别。return 0;
    }

缺省参数

  • 在定义函数时,能够给参数赋默认值(这个默认值就叫缺省值),当调用函数没有传递参数时,该参数就会应用默认值
  • 留神:给参数赋缺省值时,只能从右到左,没有缺省值的必须都在右边。
  • 能够全副缺省,也能够半缺省。
void test(int a, int b = 0, int c = 10)  // 半缺省
{
    cout << a << endl;  
    cout << b << endl;
    cout << c << endl;
}

int main()
{test(1);  // 输入为 1  0  10
   test(1,2,3); // 输入为 1 2 3
    return 0;
}

函数重载

  • C 语言中不容许定义雷同名称的函数,然而 C ++ 中能够
  • 然而 C ++ 中定义雷同名称的函数时,函数的参数必须不同(参数类型或个数不同, 与有无返回值和缺省参数无关)
  • 定义雷同名称的函数,就叫函数重载。
int add(int a,int b)
{
}

int add(char a,int b)
{
}

char add(int a,int b,int c)
{
}

int add(int a = 1,int b = 2,int c = 3) // 留神:这个函数和上一个函数就不是重载
{}

援用变量

  • 援用不是新定义一个变量,而是给曾经存在的变量取了个别名,理论内存中应用的是同一块空间。
  • 援用必须在定义时初始化,援用一旦初始化后,援用对象不会变(初始化时不能为 nullptr)
int a =10;
int d = 6;
int& b = a;  // b 是 a 的别名(援用)b = d;     // 这里 b 不是 d 的别名,这里是将 d 的值赋值给 b。int& c;   // 未初始化,会报错。
  • 留神:援用变量的权限不能比原变量大
const int a = 10;int& c = a;    
// 原变量 a 是 const 常量,不可更改,而援用 c 是 int 类型,能够更改
// 权限放大,这是谬误的

int a = 10;const int& c = a;  // a 能够更改,c 不可更改,权限放大,这是对的。
  • 在产生隐式类型转换时,会创立一个长期变量,这个长期变量是 const 类型的。
int a = 10;
double& ra = a;  // 这是谬误的
const double& ra = a; // 这是对的
// 因为隐式类型转换,会创立一个 const double 的长期变量
//ra 援用的就是这个长期变量,是长期变量的别名

援用变量作函数返回值

  • 传值返回:返回的是 c 的拷贝

    • return c 时返回的并不是 c 这个变量,而是创立一个长期变量(const int 型),将 c 的值传给长期变量,再由长期变量传递给 ret(c 是局部变量)
  • 所以如果要用援用来接管返回值,须要加 const(长期变量是 const 类型)
int add(int a,int b)
{
    int c = a + b;
    return c;
}
int main()
{int ret = add(1,2);
    const int& ret = add(1,2);
    return 0;
}
  • 传援用返回:返回的是 c 的援用

    • return c 时返回时创立的长期变量是 int& 类型
    • 也就是说 ret 接管到的是变量 c 的援用
  • 留神:变量 c 是局部变量,出函数后,就销毁,所以 ret 的值是不确定的,ret 代表的内存空间还是之前变量 c 的地址。
  • 当参数和返回值是占用的内存比拟大的时候,传援用传参和援用返回能够大大提高效率。
int& add(int a,int b)
{
    int c = a + b;
    return c;
}
int main()
{int& ret = add(1,2); // 这里创立的长期变量是 int& 类型,所以能够不加 const。// 这里 ret 的值是随机的。add(5,7);
    cout << ret << endl;  // 这里输入后果为 12
    // 因为 int& ret = add(1,2); 调用后,栈中内存被销毁,然而 ret 代表了之前变量 c 的地址
    //add(5,7); 再次调用,会在原来的栈内存中去生成这个函数,新生成的函数中变量 c 的地址还是原来的地址。// 留神:必须是两次间断调用才会呈现这种状况,因为上一次销毁内存后,没有其余数据占用栈空间
    // 其实这里是越界拜访了的。return 0;
}

援用与指针的关系

  • 从语法的角度:

    • 援用并没有开拓新空间,只是给原来的空间取了个别名
    • 而指针是开拓了一个新空间,用来存储原变量的地址。
  • 从底层汇编的角度:

    • 援用跟指针是类似的,援用的底层的解决形式跟指针一样,都是开拓新的指针空间。

内联函数 inline

  • 用 inline 润饰的函数叫内联函数,编译时 C ++ 编译器会在调用内联函数的中央开展,不存在函数压栈的开销,晋升程序的效率。
  • 间接调用函数,会在栈中创立这个函数,有栈帧耗费(每次调用函数都会在栈中创立)
  • C++ 中倡议频繁调用的小函数定义成内联函数,防止栈帧开销。
  • 应用内联函数的缺点:编译进去的可执行程序变大,执行程序耗费内存变多。
  • 内联函数是一种以空间换工夫的做法,所以不适宜代码很长或者有递归 / 循环的函数。
  • 留神:

    • 内联函数申明和定义必须放在同一文件或者在定义函数时间接申明,否则会在编译时找不到指标。
    • 内联函数不能用于缺省参数的函数中。
//inline void test(int a, int b , int c);
inline void test(int a, int b , int c)  // 定义函数时间接申明
{
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
}
int main()
{test(1, 2, 3);
    return 0;
}

关键字 auto

  • auto:主动匹配类型
  • auto 会依据 a 的类型主动定义 b 的类型。
int a = 10;
auto b = a;
  • typeid().name() 打印变量类型
cout << typeid(b).name << endl;

范畴 for 遍历(C++11 新语法)

  • 性能:主动遍历,主动将 arr 中的值赋给 a,直到完结。
  • 留神:arr 必须有确定的范畴。
int arr[] = {1,2,3,4,5,6}
for(auto a : arr) // 这里相当于 int a = arr[0],而后顺次循环
{a *= 2;  // 这里 a 是一个独立的变量,与 arr[0]无关。}

for(auto& a : arr) // 这里相当于 int& a = arr[0],而后循环
{a *= 2;  // 这里的 a 是 arr[0]的援用 (别名),所以扭转 a 也会扭转 arr[0] 的值
}
退出移动版