C++的相关知识集

1、C++概述

1 两大编程思想

c++语言在c语言的基础上添加了面向对象编程泛型编程的支持。c++继承了c语言高效,简洁,快速和可移植的传统。

2 起源

与c语言一样,c++也是在贝尔实验室诞生的,Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)在20世纪80年代开发了这种语言。

3 移植性和标准

  • ANSI 在1998制定出C第一套标准
  • 2003年,发布了c++标准第二版(IOS/IEC 14882:2003),该版本对第一版修订了一些错误,但并没有改变语言特性,因此c++98表示c++98/c++2003
  • c++不断发展。IOS标准委员会于2011年8月批准了新标准ISO/IEC 14882:2011,该标准被称为c++11,与c++98一样c++11也新增了许多特性。也是非常常见的一个版本
  • 在C++11基础上又出现了C++14和C++17

2、C++初识

#include <iostream>  //标准输入输出流   i - input  输入  o - output 输出  stream 流  相当于 stdio.h
using namespace std; //使用  标准  命名空间  //程序入口函数
int main()
{// cout  标准输出流对象// << 左移  在C++下有了新的寓意  用于在cout后拼接输出的内容   // endl   --- end line  刷新缓冲区 并且换行  cout << "hello world" << endl;system("pause");  //阻塞return EXIT_SUCCESS;  //返回正常退出
}
  • 引入头文件 #include 标准输入输出流
  • 使用标准命名空间 using namespace std;
  • 标准输出流对象 cout << "hello world" << endl;
  • 面向对象三大特性:封装、继承、多态

问题1:c++头文件为什么没有.h ?

在c语言中头文件使用扩展名.h,将其作为一种通过名称标识文件类型的简单方式。但是c++的用法改变了,c++头文件没有扩展名。但是有些c语言的头文件被转换为c++的头文件,这些文件被重新命名,丢掉了扩展名.h(使之成为c++风格头文件),并在文件名称前面加上前缀c(表明来自c语言)。例如c++版本的math.h为cmath.

头文件类型约定示例说明
c++旧式风格以.h结尾iostream.hc++程序可用
c旧式风格以.h结尾math.hc/c++程序可用
c++新式风格无扩展名iostreamc++程序可用,使用namespace std
转换后的c加上前缀c,无扩展名cmathc++程序可用,可使用非c特性,如namespace std

问题2:using namespace std 是什么 ?

namespace是指标识符的各种可见范围。命名空间用关键字namespace 来定义。命名空间是C++的一种机制,用来把单个标识符下的大量有逻辑联系的程序实体组合到一起。此标识符作为此组群的名字。

问题3:cout 、endl 是什么 ?

cout是c++中的标准输出流,endl是输出换行并刷新缓冲区。

3、C++对C的扩展

1 双冒号::作用域运算符

:: 代表作用域 ,如果前面什么都不添加 代表全局作用域

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
//using namespace std;int atk = 1000;
void test01()
{int atk = 2000;std::cout << "atk = " << atk << std::endl;// ::代表作用域  如果前面什么都不添加 代表全局作用域std::cout << "全局 atk = " << ::atk << std::endl;
}int main() {test01();system("pause");return EXIT_SUCCESS;
}

2 namespace命名空间

准备函数:

game1.h

#pragma once
#include <iostream>
using namespace std;namespace KingGlory
{void goAtk();
}

game2.h

#pragma once
#include <iostream>
using namespace std;namespace LOL
{void goAtk();
}

game1.cpp

#include "game1.h"void KingGlory::goAtk()
{cout << "王者荣耀攻击实现" << endl;
}

game2.cpp

#include "game2.h"void LOL::goAtk()
{cout << "LOL攻击实现" << endl;
}

命名空间用途:解决名称冲突

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include "game1.h"
#include "game2.h"//1、命名空间用途: 解决名称冲突
void test01()
{KingGlory::goAtk();LOL::goAtk();
}
int main() {test01();system("pause");return EXIT_SUCCESS;
}

命名空间下可以存放 : 变量、函数、结构体、类…

//2、命名空间下 可以放  变量、函数、结构体、类...
namespace A
{int m_A;void func();struct Person{};class Animal{};
}

命名空间必须要声明在全局作用域

命名空间可以嵌套命名空

//4、命名空间可以嵌套命名空间
namespace B
{int m_A = 10;namespace C{int m_A = 20;}
}
void test03()
{cout << "B空间下的m_A = " << B::m_A << endl;cout << "C空间下的m_A = " << B::C::m_A << endl;
}

命名空间是开放的,可以随时将新成员添加到命名空间下

namespace B
{int m_A = 10;
}namespace B
{int m_B = 100;
}
void test04()
{cout << "B空间下的m_A = " << B::m_A << endl;cout << "B空间下的m_B = " << B::m_B << endl;
}

命名空间可以匿名的

//6、命名空间可以是匿名的
namespace
{int m_C = 1000;int m_D = 2000;//当写的命名空间的匿名的,相当于写了  static int m_C = 1000; static int m_D = 2000;
}void test05()
{cout << "m_C = " << m_C << endl;cout << "m_D = " << ::m_D << endl;
}

命名空间可以起别名

//7、命名空间可以起别名
namespace veryLongName
{int m_E = 10000;void func(){cout << "aaa" << endl;}
}void test06()
{namespace veryShortName = veryLongName;cout << veryShortName::m_E << endl;cout << veryLongName::m_E << endl;}

3 using声明以及using编译指令

using声明

  1. using KingGlory::sunwukongId
  2. 当using声明与 就近原则同时出现,出错,尽量避免
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;namespace KingGlory
{int sunwukongId = 1;
}void test01()
{int sunwukongId = 2;//1、using声明//using KingGlory::sunwukongId ;    //当using声明与 就近原则同时出现,出错,尽量避免cout << sunwukongId << endl;
}

using编译指令

  1. using namespace KingGlory;
  2. 当using编译指令 与 就近原则同时出现,优先使用就近
  3. 当using编译指令有多个,需要加作用域 区分
namespace KingGlory
{int sunwukongId = 1;
}namespace LOL
{int sunwukongId = 3;
}
void test02()
{//int sunwukongId = 2;//2、using编译指令using namespace KingGlory;using namespace LOL;//当using编译指令  与  就近原则同时出现,优先使用就近//当using编译指令有多个,需要加作用域 区分cout << KingGlory::sunwukongId << endl;cout << LOL::sunwukongId << endl;
}

注意:使用using声明或using编译指令会增加命名冲突的可能性。也就是说,如果有名称空间,并在代码中使用作用域解析运算符,则不会出现二义性。

4 检测增强

函数检测增强

  • 函数的返回值
  • 形参类型
  • 函数调用参数个数

类型转换检测增强

char p = (char )malloc(64) C下等号必须左右一致类型

//3、类型转换检测增强
void test02()
{char* p = malloc(64);
}

以上c代码c编译器编译可通过,c++编译器无法编译通过。

struct 增强

  • C++可以在结构体中放函数
  • 创建结构体变量可以简化关键字struct
//1. 结构体中即可以定义成员变量,也可以定义成员函数;;
struct Student {string mName;int mAge;void setName(string name) { mName = name; }void setAge(int age) { mAge = age; }void showStudent() {cout << "Name:" << mName << " Age:" << mAge << endl;}
};//2. c++中定义结构体变量不需要加struct关键字
void test01() {Student student;student.setName("John");student.setAge(20);student.showStudent();
}

bool数据类型扩展

C++才有bool类型,代表真 --- 1 true 假 ---- 0 false。sizeof = 1

//5、bool类型扩展  C语言下 没有这个类型  C++有bool类型
bool flag = true; // bool类型 代表  真和假   true  ---- 真(1)    false  ---- 假(0)void test04()
{cout << sizeof(bool) << endl; //结果是1个字节//flag = false;//flag = 100; //将非0的数都转为1cout << flag << endl;
}// 结果
1
1

三目运算符增强

//6、三目运算符增强
void test05()
{//?:int a = 10;int b = 20;printf("ret = %d\n", a > b ? a : b);(a < b ? a : b) = 100; // C++下返回的是变量  a = 100printf("a = %d\n", a);printf("b = %d\n", b);
}//结果
ret = 20
a = 100
b = 20

5 const

const增强

C语言下

  • 全局const 直接修改 失败 间接修改 语法通过,运行失败
  • 局部 const 直接修改 失败 间接修改 成功
	const int constA = 10;int* p = (int*)&constA;*p = 300;printf("constA:%d\n",constA);printf("*p:%d\n", *p);//结果
constA:300
*p:300

C++语言下

  • 全局 const 和C结论一样
  • 局部 const 直接修改失败 间接修改 失败
  • const可以称为常量,可以用于数组内的常数。
void test05()
{const int constA = 10;int* p = (int*)&constA;*p = 300;cout << "constA:" << constA << endl;cout << "*p:" << *p << endl;
}//结果
constA:10
*p:300

constA在符号表中,当我们对constA取地址,这个时候为constA分配了新的空间,*p操作的是分配的空间,而constA是从符号表获得的值。

对于基础数据类型,如果用一个变量初始化const变量,如果const int a = b,那么也是会给a分配内存。

void test06()
{int b = 10;const int constA = b;int* p = (int*)&constA;*p = 300;cout << "constA:" << constA << endl;cout << "*p:" << *p << endl;}//结果
constA:300
*p:300

const 链接属性

1)C语言下const修饰的全局变量默认是外部链接属性

同一个目录下两个文件:

const int g_a = 1000;
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>int main() {extern const int g_a;printf("g_a = %d\n", g_a);system("pause");return EXIT_SUCCESS;
}

可以正常输出。

2)C++下const修饰的全局变量默认是内部链接属性

可以加extern 提高作用域

extern const int g_b = 1000;//默认是内部链接属性 可以加关键字 extern 提高作用域
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;int main(){extern const int g_b;cout << "g_b = " << g_b << endl;;system("pause");return EXIT_SUCCESS;
}

const分配内存情况

  • 对const变量 取地址 ,会分配临时内存
  • 使用普通变量 初始化 const变量(const增强中已经举例)
  • 对于自定义数据类型
//3、对于自定义数据类型 
struct Person
{string m_Name;int m_Age;
};
void test03()
{const Person p;//p.m_Age = 10;Person* pp = (Person*)&p;(*pp).m_Name = "Tom";pp->m_Age = 10;cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}

尽量用const代替define

define出的宏常量,没有数据类型、不重视作用域

const和#define区别总结:

  • const有类型,可进行编译器类型安全检查。#define无类型,不可进行类型检查
  • const有作用域,而#define不重视作用域

6 引用

1)简介

  • 目的:起别名
  • 语法: 类型(与原名类型必须一致) &别名 = 原名
  • 引用必须要初始化,引用一旦初始化后,就不可以引向其他变量
void test02()
{int a = 10;//int &b; //引用必须要初始化int& b = a;   //引用一旦初始化后,就不可以引向其他变量int c = 100;b = c; // 赋值cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}//结果
a = 100
b = 100
c = 100

2)建立对数组引用

①直接建立引用

int arr[10];

int(&pArr)[10] = arr;

②先定义出数组类型,再通过类型 定义引用

typedef int(ARRAY_TYPE)[10];

ARRAY_TYPE & pArr2 = arr;

//对数组建立引用
void test03()
{//1、直接建立引用int arr[3];int(&pArr)[3] = arr;for (int i = 0; i < 3; i++){arr[i] = 100 + i;}for (int i = 0; i < 3; i++){cout << pArr[i] << endl;}printf("\n --------2------\n");//2、先定义出数组类型,再通过类型 定义引用typedef int(ARRAY_TYPE)[3];//类型  &别名 = 原名ARRAY_TYPE& pArr2 = arr;for (int i = 0; i < 3; i++){cout << pArr2[i] << endl;}}

3)参数的传递方式

  • 值传递
  • 地址传递
  • 引用传递
//1、值传递
void mySwap01(int a, int b)
{int temp = a;a = b;b = temp;cout << ":::b = " << b << endl;*/
}//2、地址传递
void mySwap02(int* a, int* b)
{int temp = *a;*a = *b;*b = temp;
}//3、引用传递
void mySwap03(int& a, int& b) // int &a = a; int &b = b;
{int temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;//mySwap01(a, b);//mySwap02(&a, &b);mySwap03(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;
}

第一种其实没有实现交换功能。通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单:

  1. 函数调用时传递的实参不必加“&”符
  2. 在被调函数中不必在参数前加“*”符

引用作为其它变量的别名而存在,因此在一些场合可以代替指针。C++主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。

4)注意事项

  • 引用必须引一块合法内存空间
  • 不要返回局部变量的引用
int& func()
{int a = 10;return a;
}//引用注意事项
void test02()
{//int &a = 10;  //1、引用必须引一块合法内存空间,这种就不能通过,因为后面必须是变量名。//2、不要返回局部变量的引用int& ref = func();cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;
}

第一个能正常输出,是因为程序做了优化保留,实际这种做法是有潜在危险的。要想不取消,需要就加上static,看下一个例子。

  • 当函数返回值是引用时候,那么函数的调用可以作为左值进行运算
int& func2()
{static int a = 10;return a;
}void test03()
{int& ref = func2();cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;//当函数返回值是引用,那么函数的调用可以作为左值func2() = 1000;cout << "ref = " << ref << endl;
}

5)引用的本质

引用的本质在c++内部实现是一个指针常量.

Type& ref = val; // Type* const ref = &val;

c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

void testFunc(int& ref) {ref = 100; // ref是引用,转换为*ref = 100
}
int main() {int a = 10;int& aRef = a; //自动转换为 int* const aRef = &a;这也能说明引用为什么必须初始化aRef = 20; //内部发现aRef是引用,自动帮我们转换为: *aRef = 20;cout << "a:" << a << endl;cout << "aRef:" << aRef << endl;testFunc(a);cout << "a:" << a << endl;cout << "aRef:" << aRef << endl;return EXIT_SUCCESS;
}

6)指针的引用

  • 利用引用可以简化指针
  • 可以直接用同级指针的 引用 给同级指针分配空间

以下两个示例代码效果是一样的:

struct Person
{int age;
};void allocateSpace(Person** p)
{//p指向指针的指针    *p  指针 指向的是person 本体   **p  person本体*p = (Person*)malloc(sizeof(Person));(*p)->age = 10;
}void test01()
{Person* p = NULL;allocateSpace(&p);cout << "p.age = " << p->age << endl;
}
struct Person
{int age;
};void allocateSpace2(Person*& pp) // Person * &pp = p;
{pp = (Person*)malloc(sizeof(Person));pp->age = 20;
}void test02()
{Person* p = NULL;allocateSpace2(p);cout << "p.age = " << p->age << endl;
}

7)常量的引用

  • 本质:const int &ref = 10; // 加了const之后, 本质 相当于写成 int temp = 10; const int &ref = temp;当然一般不这么用。
  • 常量引用的使用场景:修饰函数中的形参,防止误操作
void test01()
{//int &ref = 10; //这种是不合法的const int& ref = 10; // 加了const之后,  相当于写成   int temp = 10;  const int &ref = temp;int* p = (int*)&ref;*p = 10000;cout << ref << endl; //可以被修改
}//常量引用的使用场景 修饰函数中的形参,防止误操作
void showValue(const int& a)
{//a = 100000;cout << "a = " << a << endl;
}void test02()
{int a = 100;showValue(a);
}//结果
1000
a = 100

推荐:

MBA智库百科,全球专业中文经管百科
​​​​​​​​​​​
 

中文维基百科 - 维基百科

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/837288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决kali linux ssh连接失败

kali linux 默认ssh是禁止root登录的 为了通过 SSH 进入你的 Kali Linux 系统&#xff0c;你可以有两个不同的选择。第一个选择是创建一个新的非特权用户然后使用它的身份来登录。第二个选择&#xff0c;你可以以 root 用户访问 SSH 。为了实现这件事&#xff0c;需要在SSH 配…

AI早班车5.11

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

经纬恒润亮相AutoSec中国汽车网络安全及数据安全合规峰会

近日&#xff0c;由谈思实验室、谈思汽车、上海市车联网协会联合举办的AutoSec 8周年年会暨中国汽车网络安全及数据安全合规峰会在上海举办。本次大会主要聚焦数据合规、汽车网络与数据安全趋势与挑战、软件供应链安全、车辆网络安全、网络安全管理等话题。经纬恒润作为智能网联…

C语言 [力扣]详解环形链表和环形链表II

各位友友们&#xff0c;好久不见呀&#xff01;又到了我们相遇的时候&#xff0c;每次相遇都是一种缘分。但我更加希望我的文章可以帮助到大家。下面就来具体看看今天所要讲的题目。 文章目录 1.环形链表2.环形链表II 1.环形链表 题目描述:https://leetcode.cn/problems/link…

部署Discuz论坛项目

DIscuz 是由 PHP 语言开发的一款开源社交论坛项目。运行在典型的LNMP/LAMP 环境中。 安装MySQL数据库5.7 主机名IP地址操作系统硬件配置discuz-db192.168.226.128CentOS 7-mini-20092 Core/4G Memory 修改主机名用来自己识别 hostnamectl set-hostname discuz-db #重连远程…

uniapp h5 配置代理服务器

"devServer": {"disableHostCheck": true,"proxy": {"/api": {// 需要被代理的后台地址"target": "http://自己的地址","changeOrigin": true,"secure": false,"pathRewrite": {&q…

机器学习(2)

目录 2-1泛化能力 2-2过拟合和欠拟合 2-3三大问题 2-4评估方法 2-5调参和验证集 2-6性能度量 2-7比较检验 2-1泛化能力 如何进行模型评估与选择&#xff1f; 2-2过拟合和欠拟合 泛化误差&#xff1a;在“未来”样本上的误差 经验误差&#xff1a;在训练集上的误差&am…

每日OJ题_贪心算法四⑧_力扣767. 重构字符串

目录 力扣767. 重构字符串 解析代码 力扣767. 重构字符串 767. 重构字符串 难度 中等 给定一个字符串 s &#xff0c;检查是否能重新排布其中的字母&#xff0c;使得两相邻的字符不同。 返回 s 的任意可能的重新排列。若不可行&#xff0c;返回空字符串 "" 。 …

鸿蒙系统编译方式

鸿蒙系统编译 编译原理编译方式概述hb编译ohos-buildhb安装编译使用build脚本hpmhpm介绍编译举例说明综合应用举例虚拟机中编译docker中使用hpm编译编译原理 编译构建指导:https://docs.openharmony.cn/pages/v4.0/zh-cn/device-dev/subsystems/subsys-build-all.md,文档介绍…

设计模式 六大原则之里氏替换原则

文章目录 概念替换逻辑行为不变 拆解小结 概念 子类对象能够替换程序中父类对象出现的任何地方&#xff0c;并且保证原来程序的逻辑行为不变及正确性不被破坏。 替换 替换的前提是面向对象语言所支持的多态特性&#xff0c;同一个行为具有多个不同表现形式或形态的能力。 逻…

Android adb shell关于CPU核的命令

Android adb shell关于CPU核的命令 先使用命令&#xff1a; adb shell 进入控制台。 然后&#xff0c;直接在$后面输入下面命令&#xff0c;针对CPU的命令。 cat /proc/cpuinfo | grep ^processor | wc -l 查看当前手机的CPU是几核的。 cat sys/devices/system/cpu/online …

Java面试八股之什么是Java反射

什么是Java反射 基本概念 反射是Java语言的一个重要特性&#xff0c;它允许我们在运行时分析类、接口、字段、方法等组件的信息&#xff0c;并能够动态地操作这些组件&#xff0c;包括创建对象、调用方法、访问和修改字段值等。简单来说&#xff0c;反射提供了在程序运行时对…

【kubeflow文档】kubeflow介绍与架构

1. kubeflow介绍 Kubeflow项目致力于使机器学习&#xff08;ML&#xff09;工作流在Kubernetes上的部署变得简单、可移植和可扩展。目标不是重新创建其他服务&#xff0c;而是提供一种直接的方法&#xff0c;将ML的开源系统部署到不同的基础设施中。无论在哪里运行Kubernetes&a…

Shell的运行原理和Linux的权限

Shell的运行原理 Linux严格意义上说是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;”&#xff0c;但我们一般用户不能直接使用kernel&#xff0c;而是通过kernel的“外壳程序”&#xff0c;也就是所谓的Shell&#xff0c;来与kernel沟通。 Shell…

Operations Research课程之非线性规划(梯度下降|牛顿法|Gurobi+Python)

目录 1.非线性规划介绍 2.梯度下降法(Gradient descent) 2.1 梯度和Hessians矩阵 2.2 梯度下降算法 2.3 算法举例 3. 牛顿法(Newton’s method) 3.1 适合单变量的牛顿法 3.2 适合多变量的牛顿法 3. 实例(GurobiPython) 3.1 Agricultural Pricing问题描述 3.2 Gurobi…

【论文复刻】堆叠柱状图+饼图

复刻了一下这篇论文里的fig2c&#xff1a;Impacts of COVID-19 and fiscal stimuli on global emissions and the Paris Agreement | Nature Climate Change 效果图&#xff1a; 主要步骤&#xff1a; 1. 数据准备&#xff1a;随机赋值 2. 图像绘制&#xff1a;绘制堆叠柱状…

【C++】可变参数模板简单介绍

前言 可变参数模板是C11中的新特性&#xff0c;它能够让我们创建可以接收可变参数的函数模板和类模板&#xff0c;相比C98/03&#xff0c;类模版和函数模版中只能含固定数量的模版参数&#xff0c;可变模版参数是一个巨大的改进&#xff0c;通过系统系统推演数据的类型&#xf…

Python笔记-Alchemy中改变表的模式(库schema)

现在是2024-01-10&#xff0c;发到互联网上应该是2024-05-13。查了下chatgpt&#xff0c;麻了&#xff0c;乱七八糟的。 最后还是靠stackoverflow解决的&#xff0c;目前&#xff0c;从解决问题的角度来看&#xff0c;这个还是牛逼点。 原文如下&#xff1a; python - How d…

Ansible常用变量【下】

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 前言 在上一篇文章《Ansible常用变量【上】》中&#xff0c;学习了Ansible常用变量的前半部分&#xff0c;放了个五一假&#x…

买货查窜货过程中的可能情况

控价除了要管控渠道中的低价、乱价链接外&#xff0c;还可能需要解决窜货问题&#xff0c;当窜货问题蔓延不及时解决时&#xff0c;渠道会越来越受影响&#xff0c;所以治理窜货也是控价过程中很重要的一步&#xff0c;窜货问题的治理多通过买货溯源来解决&#xff0c;买货要先…