【C++】---基础特性

简介: 【C++】---基础特性

C++是一门在C语言的基础上改进后的语言,从面向过程过渡到面向对象

因此在C++的使用过程中同样保留了C语言的特性,在一份C++代码中也可与去使用C语言的语法进行编写

命名空间

在使用C语言的过程就会发现,同一样的代码里面并不能出现同名的变量或者函数,如果是一个多人合作的项目难免会出现同名的状况。C++为了避免这种状况就引入了命名空间这个概念。

使用命名空间的目的就是避免命名冲突。将定义的变量或者函数放在不同的空间里,不同空间里的变量或者函数不会引起冲突,需要用到某个空间里的某个成员时再将其调用出来,这样就可以有效的避免上述情况的发生。

命名空间可以由用户自由定义,当然C++本身也定义了空间,基本上能够使用到的库函数都在空间std里面。如果需要自己去定义一个空间就需要以下代码格式。

//namespce是命名空间的关键字
//name代表命名空间的名字可以自己定义
//后面必须要带上{},定义好后{}里面的内容就是这个空间的内容
namespace name{
    //空间里的成员
  void print(){}
    int a;
}

那么定义好了空间后就可以对空间里的成员进行调用了

//指定某个空间里的成员需要用带 :: 空间名字::空间成员
name::print();
name::a;
std::string s;

当然如果每一个函数都要用这种方式的话就会略微有些麻烦,因此在平常写小项目时不太会有冲突的情况下也可以将整个空间都放开

//using namespace 是代表将整个空间都放开
//name 代表需要放开的空间的名字
using namespace name;
//放开整个空间后就不再需要指定去调用
print();
a;

补充:

  1. 同一个工程里可以有多个相同名称的空间,编译器会自动将它们合成为同一个空间
  2. 一个空间就定义了一个新的作用域,空间中的所有内容都局限于其中
  3. using namespace代表放开整个空间,而也可以使用 using name::a 代表仅放开一个成员

输入/输出

C语言的输入输出可以使用函数 printf()\scanf()

同样C++也有属于自己独特的输入输出,其输入和输出并不用像C语言那样需要指定数据类型,而是会自动的去识别数据类型

cout 表示标准输出,cin 表示标准输入,endl 表示换行

在使用cout和cin时还需要搭配对应的运算符,<< 是流插入运算符,>> 是流提取运算符

并且使用是还需包含上头文件以及它们都是存放在std命名空间里的

#include<iostream>
using namespace std;
int main() {
  int a = 10;
  cout << a << endl;
  cout << "hello world" << endl;
  cin >> a;
  cout << a << endl;
  return 0;
}

cb54b2502c92656ac92540414c828ebb.png

缺省参数

缺省参数实际上就是在定义或者声明一个函数时为函数的参数指定一个值,调用函数时如果没有给函数传值那函数就默认使用缺省值

#include<iostream>
using namespace std;
int Add(int a = 10, int b = 20) {
  return a + b;
}
int main() {
    //没有传参时默认使用缺省值,因此结果为10 + 20
  int i = Add();
  cout << i << endl;
    //只传一个参数时,默认根据顺序传参因此a此时接收参数,5 + 20
  i = Add(5);
  cout << i << endl;
    //两个都传参时,5 + 5
  i = Add(5, 5);
  cout << i << endl;
  return 0;
}

98f9932f1118ccc976148e1932844fb6.png


缺省参数分类:

  1. 全缺省:也就是函数所有的参数都给定缺省值
  2. 半缺省:只有某些个参数给定缺省值,这个需要特别注意,半缺省的参数必须依照从右到左的顺序给定,也就是说如果指定某个参数为缺省值时它的右边那个参数也必须要有左边的可以没有

对于缺省参数,不能同时在声明和定义的时候存在,给定的缺省值必须是常量或者全局变量不能是局部变量

函数重载

函数重载是指一个同名的函数执行不一样的结果,也就是说同一个作用域里可以有同名的函数,这里和上面所讲的命名冲突是有区别的。

一个作用域里想要出现同名的函数必须要构载重载,而重载是有前提条件的。

同名函数的参数类型不同

同名函数的参数个数不同

同名函数的参数顺序不同

#include<iostream>
using namespace std;
//同名函数参数类型不同
int Add(int a, int b) {
  return a + b;
}
double Add(double a, double b) {
  return a + b;
}
//同名函数参数个数不同
int Reduce(int a, int b) {
  return a - b;
}
int Reduce(int a, int b, int c) {
  return a - b - c;
}
//同名函数参数顺序不同
void print(char c, int a) {
  cout << a << " " << c << endl;
}
void print(int a, char c) {
  cout << c << " " << a << endl;
}
int main() {
  cout << Add(10, 20) << endl;
  cout << Add(5.5, 4.5) << endl;
  cout << Reduce(10, 5) << endl;
  cout << Reduce(15, 5, 5) << endl;
  print('a', 10);
  print(10, 'a');
  return 0;
}


85e1226161958399d5a2a35c26f1ca6c.png

上述情况就可以构造函数的重载。

引用

引用是指给一个已有的变量取一个别名,但不是定义一个新的变量,它与它引用的那个变量共用一块内存空间。也就是说对这个引用操作也就是对那个已有变量操作。

#include<iostream>
using namespace std;
int main() {
  int a = 10;
  int& b = a;
  cout << a << "->" << b << endl;
  b = 20;
  cout << a << "->" << b << endl;
  return 0;
}

80c489e74bbdea35b0e56269cf8a329d.png

引用在定义时必须初始化

一个变量可以有多个

引用引用一旦引用一个实体,再不能引用其他实体

const变量要用const引用才可以

引用的使用场景

一个函数在传参或者返回值的过程中都需要进行拷贝的,当函数返回一个值的时,由于该值是一个局部变量除了函数后就会被销毁因为编译器会创建一个临时变量将返回值拷贝给它,然后再将临时变量的值拷贝给接收值的变量。如果这个返回值很大的时候性能就会大大降低。传参也是类似的情况,因此引用做返回值和参数的作用就出现了。

当使用引用传参时,参数就会变成传入的那个变量的别名就可以减少拷贝,修改这个引用也就会修改变量和指针类似不过指针是传入地址。做返回值时也是可以减少拷贝,返回的那个变量就是接收的那个变量的别名。

需要注意的是:如果函数返回时出了函数作用域返回对象还未还给系统,则可以使用引用返回。如果已经还给系统了,则必须使用传值返回

引用和指针的区别

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间,但实际上在底层引用是按照真真的方式实现的是具有空间的。没有NULL引用,但有NULL指针。有多级指针,但是没有多级引用。

内联函数

调用函数是需要建立栈帧的,如果一个函数被多次调用就会多次建立栈帧开销就会很大。因此内联函数就是将函数展开变成一个函数体而不是一个单独的函数,这样就可以减少栈帧的开销提高效率。

这是一种以空间换时间的做法,会使得目标文件变大。当一个函数需要多次调用并且函数的内容不是很大时就可以使用内联函数

inline修饰的函数就是内联函数

便捷操作(C++11)

范围for

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

#include<iostream>
using namespace std;
int main() {
  int a[] = { 1,2,3,4,5,6 };
  for (auto e : a)
    cout << e << " ";
  cout << endl;
  return 0;
}

image.png

有迭代器的容器并且迭代的对象实现了++和==的操作都可以使用范围for

auto

有一些类型很长导致写起来容易出错,auto就可以自动识别类型。

#include<iostream>
using namespace std;
int main() {
  int a[] = { 1,2,3,4,5,6 };
  auto b = a[4];
  cout << b << endl;
  return 0;
}

9c486bc0a26aee745b13ff11e0e41dd0.png

目录
相关文章
|
2月前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
123 59
|
2月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
2月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
2月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
2月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
2月前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
41 0
|
3月前
|
编译器 C++ 计算机视觉
C++ 11新特性之完美转发
C++ 11新特性之完美转发
54 4
|
3月前
|
Java C# C++
C++ 11新特性之语法甜点1
C++ 11新特性之语法甜点1
34 4
|
3月前
|
安全 程序员 编译器
C++ 11新特性之auto和decltype
C++ 11新特性之auto和decltype
44 3
|
3月前
|
设计模式 缓存 安全
C++ 11新特性之week_ptr
C++ 11新特性之week_ptr
39 2