C++初阶------------------入门C++(二)

简介: C++初阶------------------入门C++(二)

C++初阶------------------入门C++(一)

https://developer.aliyun.com/article/1499029


缺省参数

我们知道在C语言中,函数的有参数就必须传参,不传参就会报错,为了解决这个问题,c++就有了可以拥有默认参数的函数

#include<iostream>
using std::cout;
using std::endl;
using std::cin;
namespace ncon
{
  void Func(int a = 10)
  {
    cout << a << endl;
  }
  void Func1(int a = 10, int b = 20, int c = 100)
  {
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
  }
}
using namespace ncon;
int main()
{
  ncon::Func();
  ncon::Func(30);
  Func1();
  Func1(100);
  Func1(1,1,1);

  return 0;

需要注意的是缺省值只能从右往左给,必须是连续给

还有一些是半缺省的函数

void Func(int a, int b = 10, int c = 20)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

半缺省参数必须从右往左依次来给出,不能间隔着给

声明和定义不能同时给参数,只能在声明的时候给。这个是一个默认规定

在头文件中

缺省值必须是常量或者全局变量


函数重载

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这

些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型

不同的问题。

#include<iostream>
using std::cout;
using std::endl;
using std::cin;
//参数类型不同
int Add(int a, int b)
{
  return a + b;
}
double Add(double a, double b)
{
  return a + b;
}
//参数个数不同
void Fun()
{
  cout << "Fun()" << endl;
}
void Fun(int a)
{
  cout << "Fun(int a)" << endl;
}
// 参数的顺序不同
void f(int a, double b)
{
  cout << a << endl;
  cout << b << endl;
}
void f(double b,int a)
{
  cout << a << endl;
  cout << b << endl;
}
int main()
{
  Add(1, 2);
  Add(1.1, 2.2);
  Fun();
  Fun(6);
  f(1, 2.2);
  f(2.2, 6);


  return 0;
}

参数类型不同
参数个数不同
参数的顺序不同

为啥c++支持函数重载,而C语言不行

我们前面学习过C语言的编译链接,

第一步是预处理 :主要进行头文件的展开、宏替换、条件编译(#define 、 #if #endif)以及去掉注释等

生成.i文件

第二步编译:生成汇编代码(主要)或者语法错误

生成.s文件


第三步 汇编:转换成二进制的机器码

生成.o文件(Linux环境下) (在windows是obj文件)


第四步 链接: 合并到一起,链接一些没有确定函数地址、符号表的合并和重定义


C语言不能函数重载的原因:,因为C语言在链接的时候就是使用函数名去找(C语言不存在同名函数),而c++不能使用函数名去找

objdump -S test1c#test1c是一个.out文件

在Linux中C语言函数的调用是通过函数名去找对应的函数找到对应的地址

而在c++ 中

g++ test1.c -o test1cpp

objdump -S test1cpp

为啥这里的会这么奇怪,这个函数调用的名字 是由Linux的函数名修饰规则决定的,

_Z3Adddd

写法为:

_Z + 函数名的字符个数 + 函数名 + 每个参数的第一个字符(int a 就取i)


通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修

饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。


引用

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空

间,它和它引用的变量共用同一块内存空间。

#include<iostream>
using std::cout;
using std::endl;
using std::cin;
int main()
{
  int a = 0;
  int b = a;
  int& c = a;
  c = 2;
  return 0;
}

int& c = a;//引用a

int& :引用类型

引用我们可以看作是取别名,改变c或者改变a 都会改变值,而b是一个变量,存储a的值,改变a或者b都不会改变对方

引用的好处

传参

前面我们学习过C语言如果要改变变量的值,要传地址

C语言版:

int exchang(int* a, int* b)
{
  int temp = *a;
  *a = *b;
  *b = temp;
}

c++版:

int exchang(int& left, int& right)
{
  int temp = left;
  left = right;
  right = temp;
  return left;
}

引用的注意:

  1. 引用的时候必须初始化
  2. 引用的指向是唯一的,指定了就不能更改,所以说引用和指针是不能相互取代的
  3. 一个对象可以有多个引用,但是一个引用不能拥有多个对象
  4. 引用参数比直接传参的效率要高,引用参数和传地址参数的效率相似以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。


#include<iostream>
#include<time.h>
using std::cout;
using std::endl;
using std::cin;
void Fun1(int& a)
{

}
void Fun(int a)
{

}
int main()
{
  int a = 12;
  int b = a;
  int i = 0;
  int begin1 = clock();
  for(i = 0; i < 1000000; i++)
    Fun1(a);
  int end1 = clock();
  int begin2 = clock();
  for (i = 0; i < 1000000; i++)
    Fun(a);
  int end2 = clock();
  cout << end1 - begin1 << endl;
  cout << end2 - begin2 << endl;
  return 0;
}

返回值

在C语言中我们返回一个函数的值的时候,不是返回这个变量

int exchang(int a, int b)
{
  int temp = a;
  a = *b;
  b = temp;
  return a;
}

我们知道函数栈帧的创建和销毁,知道返回值是存在寄存器里面返回的

而在c++中

int& exchang(int left, int right)
{
  int temp = left;
  left = right;
  right = temp;
  return left;
}

返回的是left的引用,因为left在函数结束的时候就销毁了,所以返回的值是随机值,这样写是错误的写法,前面我们学习过递归的实现,空间是可以重复利用的,

#include<iostream>
#include<time.h>
using std::cout;
using std::endl;
using std::cin;
int& Fun(int a)
{
  int c = a;
  c++;
  return c;
}
int main()
{
  int& num1 = Fun(6);
  cout << num1 << endl;
  cout << num1 << endl;
  Fun(1000);
  cout << num1 << endl;

  return 0;
}

这个代码可以看出来,num1引用的是c的原来的地址,函数结束,c销毁,但是那块内存还是存在,每次再调用,就会进行重复利用这块空间

正确的写法:

使用静态变量

前面我们知道如果使用静态变量的话,在静态区创建,而不是在栈区创建,这样就可以在函数销毁的时候静态变量不进行空间的释放

#include<iostream>
#include<time.h>
using std::cout;
using std::endl;
using std::cin;
int& Fun(int a)
{
  static int c = a;
  c++;
  return c;
}
int main()
{
  int& num1 = Fun(6);
  cout << num1 << endl;
  cout << num1 << endl;
  Fun(1000);
  cout << num1 << endl;

  return 0;
}

静态变量只初始化一次

某些场景

#include<iostream>
#include<time.h>
#include<assert.h>
using std::cout;
using std::endl;
using std::cin;
typedef struct Seqlist
{
  int a[100];
  int size;
}SL;
void SLModify(SL *ps, int pos, int x)
{
  assert(ps);
  assert(ps->size > pos);
  ps->a[pos] = x;
}

int& SLModify(SL* ps, int pos)
{
  assert(ps);
  assert(ps->size > pos);
  return ps->a[pos];
}

int main()
{
  SL lis = { {0},100 };
  int i = 0;
  for (i = 0; i < lis.size; i++)
  {
    SLModify(&lis, i)++;
  }


  return 0;
}

这里创建一个顺序表,如果要进行顺序表的每个元素进行加1,有两种方法,要么传地址,要么引用出来

常引用

这里介绍一下

const int a = 10;

这个 在c++中是常量,在C语言中是常变量

#include<iostream>
#include<time.h>
#include<assert.h>
using std::cout;
using std::endl;
using std::cin;

int main()
{
  //引用权限不能放大
  const int a = 10;
  //int& b = a;错误的
  const int& b = a;

  //权限可以缩小
  int c = 20;
  const int& d = c;
  const int& f = 10;
  return 0;
}

在常数中,如果对常数进行引用,就不会随便的放大权限,常数不能更改,所以对应引用也不能更改,


C++初阶------------------入门C++(三)

https://developer.aliyun.com/article/1499036

相关文章
|
14小时前
|
存储 安全 编译器
【C++】C++入门(下)
【C++】C++入门(下)
|
1天前
|
算法 编译器 C语言
从C语言到C++⑩(第四章_模板初阶+STL简介)如何学习STL(下)
从C语言到C++⑩(第四章_模板初阶+STL简介)如何学习STL
4 0
|
1天前
|
编译器 C语言 C++
从C语言到C++⑩(第四章_模板初阶+STL简介)如何学习STL(上)
从C语言到C++⑩(第四章_模板初阶+STL简介)如何学习STL
5 0
|
1天前
|
编译器 C语言 C++
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr(下)
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr
7 0
|
1天前
|
存储 安全 编译器
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用(下)
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用
4 0
|
1天前
|
存储 编译器 C语言
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用(中)
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用
4 0
|
1天前
|
自然语言处理 编译器 C语言
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用(上)
从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用
9 0
|
1天前
|
编译器 C语言 C++
从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)(下)
从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)
5 0
|
1天前
|
Java 编译器 C#
从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)(上)
从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)
11 0
|
5天前
|
编译器 C++
C++入门(命名空间)
C++入门(命名空间)