C++入门 | 函数重载、引用、内联函数

简介: C++入门 | 函数重载、引用、内联函数

C++入门 | 函数重载、引用、内联函数

一、函数重载

结论:函数名相同 参数不同(类型相同、个数相同、顺序不同)返回值可同可不同。

1. 函数重载概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数/类型/类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

2. 函数重载的使用

#include<iostream>
using namespace std;
//1.参数类型不同
int Add(int a, int b)
{
  cout << "int Add(int a, int b)" << endl;
  return a + b;
}
double Add(double a, double b)
{
  cout << "double Add(int a, int b)" << endl;
  return a + b;
}
//2.参数个数不同
void func()
{
  cout << "func()" << endl;

}
void func(int a)
{
  cout << "func(int a)" << endl;
}
//3.参数类型顺序不同
void func(int a, char b)
{
  cout << "f(int a, char b)" << endl;
}
void func(char a, int b)
{
  cout << "f(char a, int b)" << endl;
}
int main()
{
  Add(3,4);
  Add(3.5, 3.7);

  func();
  func(10);

  func(20, 'a');
  func('a', 20);

  return 0;
}

二、引用

结论:引用就是给已经存在的变量取别名,不是重新定义一个变量。


1. 引用概念

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

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

void Test1()
{
  int a = 10;
  int& b = a;// 定义引用类型
  printf("a的地址:%p\n", &a);
  printf("b的地址:%p\n", &b);

}

int main()
{

  Test1();
  return 0;
}

输出结果:

2. 引用特性

结论:引用必须初始化。不可以直接定义int& s;

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
void Test2()
{
  int s = 10;
  //int& s;  编译出错
  int& rs = s;
  int& rrs = s;
  printf("s的地址:%p\nrs的地址:%p\nrrs的地址:%p\n", &s, &rs, &rrs);
}

3. 常引用

结论:const可以使变量变为常量

在C++中,const是用于指定一个变量为常量(constant)的关键字。使用const关键字声明的变量不能被修改。它可以用于声明常量值、函数参数、函数返回值和成员函数。

void Test3()
{
  const int a = 10;
  //int& ra = a; //编译时出错,a是常量
  const int& ra = a;
  
  
  //int& b = 10; //编译时出错,b是常量
  const int& rb = 10;
  
  
  double d = 10.15;
  //int& rd = d;//编译时出错,类型(double)不同
  const double& rd = d;
  
}

4. 引用的使用场景

4.1 参数

引用做参数传值

void Swap(int& left, int& right)
{
  int temp = left;
  left = right;
  right = temp;
}
void Swap(int*left, int* right)
{
  int temp = *left;
  *left = *right;
  *right = temp;
}
int main()
{
  int a = 2;
  int b = 3;
  //引用传值交换
  Swap(a, b);
  cout << a << " " << b << endl;
  //指针传值交换
  Swap(&a, &b);
  cout << a << " " << b << endl;
  return 0;
}
4.2 返回值

使用引用做返回值

int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n;
}
int main()
{
  int ret=Count();
  cout << ret << endl;
  return 0;
}

5. 传值&传引用效率对比

结论:传引用比传值效率高

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直

接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效

率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

测验代码:

#include<iostream>
#include <time.h>
using namespace std;
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{
  A a;
  // 以值作为函数参数
  size_t begin1 = clock();
  for (size_t i = 0; i < 10000; ++i)
    TestFunc1(a);
  size_t end1 = clock();
  // 以引用作为函数参数
  size_t begin2 = clock();
  for (size_t i = 0; i < 10000; ++i)
    TestFunc2(a);
  size_t end2 = clock();
  // 分别计算两个函数运行结束后的时间
  cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
  cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
  TestRefAndValue();
  return 0;
}

输出结果:

6. 引用&指针区别

结论:从语法概念上引用只是取别名,没有独立的空间,但从底层实现上是有空间产生的,因为引用是按照指针方式来实现的。

#include<iostream>
using namespace std;
int main()
{
  int a = 10;
  int& ra = a;
  ra = 20;
  int* pa = &a;
  *pa = 20;
  return 0;
}

引用和指针的汇编代码对比:

引用和指针的不同点:

引用在定义时必须初始化,指针没有要求


引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体


没有NULL引用,但有NULL指针


在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)


引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小


有多级指针,但是没有多级引用


访问实体方式不同,指针需要显式解引用,引用编译器自己处理


引用比指针使用起来相对更安全

三、内联函数

结论:内联函数是一种用于提高函数调用效率的优化手段,适用于函数体简单且执行时间短的函数。但是在使用时需要根据具体情况进行权衡和选择。

1. 内联函数概念

C++内联函数是一种特殊的函数,它在编译时会被直接插入到调用它的地方,而不是通过跳转到函数的地址来进行调用。内联函数的主要目的是提高函数调用的效率,避免因函数调用带来的额外开销,例如压栈、跳转等操作。


使用内联函数可以有效地减少函数调用的开销,因为内联函数的代码会直接插入到调用它的地方,而不需要通过函数调用来执行。这就意味着在执行过程中不需要额外地保存和恢复函数的上下文信息,也不需要进行函数调用和返回的跳转。


要定义一个内联函数,需要在函数定义前加上关键字inline。内联函数的定义通常写在头文件中,以便在多个cpp文件中进行共享。

2. 内联函数特性

用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运

行效率。

inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建

议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不

是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性

inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址

了,链接就会找不到。

3. 内联函数的使用

#include<iostream>
using namespace std;
//内联函数
inline int Add1(int a,int b)
{
  return a + b;
}

int main()
{
  int ret = Add1(3, 5);
  cout << ret << endl;
  return 0;
}
目录
相关文章
|
8月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
118 0
|
12月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
11月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
11月前
|
C++
|
程序员 C++
C++中的函数重载有什么作用
【10月更文挑战第19天】C++中的函数重载有什么作用
234 3
|
编译器 程序员 C++
C++中的函数重载是什么
【10月更文挑战第19天】C++中的函数重载是什么
538 0
|
12月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
10月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
400 12
|
8月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
212 0
|
8月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
339 0