【c++基础】第一章 C到C++过度阶段

news2024/10/7 14:26:39

第一章 C到C++过度阶段

  • 第一个C++程序:
  • 使用`namespace+名字`
  • using关键字
  • `bool`类型
  • string字符串
  • 结构体struct
  • 结构体成员函数指针的获取方式
  • `const`关键字:
  • 内联函数
  • 函数缺省值:
  • 函数重载:
  • 引用(quote)
  • 开辟空间

第一个C++程序:

//输入输出流,c++标准头里没有.h
#include <iostream>
//标准名字空间,避免同名多人协作开发标识符冲突的问题
using namespace std;

int main(int argc, char const *argv[])
{
	int i;
    cout << "Hello world!!!" << endl; //输出
    cin >> i;//输入
    return 0;
}

编译:

g++ hello.c //g++是gcc的提升,g++可以编译的,gcc有的不可

使用namespace+名字

namespace A{
	int a=50;
	void showInfo(){
		cout <<"我在A中"<< endl;
	}
	//名字空间也可以互相嵌套
	namespace B{
		int a=200;
		void showInfo(){
			cout <<"我在A中的B中"<< endl;
		}
	}
}
namespace B{
	int a=100;
	void showInfo(){
		cout <<"我在B中"<< endl;
	}
}

int main(){
	//使用::域名信息符,访问指定空间的变量和函数
	//使用方式:名字空间::变量/函数
	cout << A::a << endl;
	cout << B::a << endl;
    cout << A::B::a << endl;
    A::showInfo();
    B::showInfo();
    A::B::showInfo();
	return 0;
}

名字空间,相当于对全局作用域进行分隔。

using关键字

  1. using+具体某个域中的标识:指定具体导入 如:using std::cout; using std::endl;
  2. using+namespace+名字空间:指定某个空间全部导入 如:using namespace std;
  3. 起别名 , 相当于typedef 的作用 如:using uint32=int;

bool类型

只有两个值(1true、0false)

#include <iostream>

using namespace std;

int main()
{
    bool ok;
    ok = true;
    cout << ok <<endl;
    ok = false;
    cout << ok << endl;
    return 0;
}

string字符串

std::string

边界检查:str.at(110);//解决越界问题

#include <iostream>

using namespace std;
using std::string;

int main()
{
    string str="yao";

//    cout << str[100] << endl;//越界,不提示
//    cout << str.at(100) << endl;//越界,提示错误
    const char *c_str =str.c_str();//使用c指针访问字符串
    cout << c_str << endl;//yao
    
    cout << str.front() << endl;//字符串第一位API 即:y
    cout << str.back() << endl;//字符串最后一位API 即:o
    cout << str.length() << endl;//字符串的长度API 即:3
    cout << str.size() << endl;//字符串的大小API(不同于c字符串,没有'\0') 即:3
    
    string str1="liang";
    cout << str+str1 << endl;//追加字符串
    str+=str1;
    cout << str << endl;//yaoliang
    str.append(str1);//API追加字符串
    cout << str << endl;//yaoliangliang
    return 0;
}

结构体struct

  1. 可以定义函数,直接复制,不像c中声明
  2. 具有封装性,默认public,也可设置成private(私有的)
  3. class是struct衍生而来,默认是private
#include <iostream>

using namespace std;

struct stu{
public:
    string name="yaoliang";
    static int salary;
    int age;
    void write_code()
    {
        cout << "writing" << endl;
    }
};

//结构体大小
//1.与非代码段和非静态区相关,函数在代码段(所以不计算),static修饰的变量在静态区(所以不计算)
//2.string 的大小为32,在64位系统,以8字节对齐

int main()
{
    stu s;
    s.age=18;
    cout << s.age << endl;//18
    cout << s.name << endl;//yaoliang
    s.write_code();//write.ing
    cout << sizeof(stu) << endl;//40   (字符串32位+int(8字节对齐))
    return 0;
}

结构体成员函数指针的获取方式

&的扩展

#include <iostream>

using namespace std;
struct Stu{
    string name;
    int age;
    void show_stuInfo(){
        cout << "姓名:" << name << ",年龄:" << age << endl;
    }
};

void show_Info(){
    cout << "加油!!!" << endl;
}

int main()
{
    int a=10;
    int *p=&a;
    cout << *p << endl;
    int arr[3]={1,2,3};
    int (*parr)[3]=&arr;
    cout << **parr <<endl;

    void (*func)()=show_Info;
    func();

    struct Stu s={"yaoliang",18};
    s.show_stuInfo();

    void (Stu::*func1)()=&Stu::show_stuInfo;//理解:指针访问结构体函数需要取地址
    (s.*func1)();

    return 0;
}

在c++中的作用域:全局作用域,局部作用域(包括语句块作用域),类域,名字空间作用域

const关键字:

int a=100;
printf("%d\n",*p);
const int *p=&a;//指针可变,a值不能变
int const *p=&a;//指针可变,a值不能变
int * const p=&a;//指针不可变,a值可以改变
const int * const p=&a;//都不可改变
总结:const修饰指针,看*,*前+const,数值不变,*后+const,指针指向不变
#include <iostream>

using namespace std;

//所以在c++中,用下面这个
const int my_max = 1024;
//(在编译阶段替换,优于#define MAX 1024(在预处理阶段,不安全,error不好找))

int main()
{
    const int a=10;
    int *p=(int *)&a;
    *p=500;
    cout << " a = " << a << endl;//10
    cout << " *p = " << *p << endl;//500
    //原因:编译优化:const修饰的变量承接的是一个常量值,
    //编译器在编译阶段,将自动把a当作一个常量
    
    const int volatile b=20;//volatile 防止编译优化,可以随时改变
    int *q=(int *)&b;
    *q=200;
    cout << " b = " << b << endl;
    cout << " *q = " << *q << endl;
    return 0;
}

内联函数

条件:不能耗时,不能循环,不能递归,代码精简(3不1精)

功能:解决C中宏函数的问题。

宏函数的优势:没有函数调用的过程,没有函数栈帧的开辟,没有函数的跳转

内联函数的作用:大大提高了程序的运行效率,但是也有代价的,最终可执行代码膨胀

#include <iostream>

using namespace std;
#define min_i(x,y)    ((x)<=(y)?(x):(y))
#define min_t(type,x,y) ({type _x = x;type _y = y;_x<_y?_x:_y;})
#define min(x,y)    ({\
                      const typeof(x)  _x = (x);\
                      const typeof(y) _y = (y);\
                      _x<_y?_x:_y;\
                     })
//内联函数
inline int my_min(int x,int y){
    return x<y?x:y;
}

int main()
{
    int a = 10;
    int b = 20;
    cout << "min_i(a++,b++)=" << min_i(a++,b++) << endl;//11
    cout << "a=" << a << endl;//12
    cout << "b=" << b << endl;//21

    a=10;
    b=20;
    cout << "min_t(int,a++,b++)=" << min_t(int,a++,b++) << endl;//10
    cout << "a=" << a << endl;//11
    cout << "b=" << b << endl;//21

    a=10;
    b=20;
    cout << "min(int,a++,b++)=" << min(a++,b++) << endl;//10
    cout << "a=" << a << endl;//11
    cout << "b=" << b << endl;//21

    a=10;
    b=20;
    cout << "my_min(a++,b++)=" << my_min(a++,b++) << endl;//10
    cout << "a=" << a << endl;//11
    cout << "b=" << b << endl;//21

}

define和inline的区别:

  1. 内联函数在编译时展开,define在预处理阶段展开
  2. 内联函数直接嵌入到目标代码中,宏只做一个简单的文本替换
  3. 内联函数在编译阶段有类型检测,语法处理等功能,而宏没有
  4. inline是函数,宏不是

函数缺省值:

#include <iostream>

using namespace std;

int add(int a=2,int b=1){//从右往左依次赋值,不能跳跃,原因入栈先后顺序
    return a+b;
}

int main()
{
    int a=10,b=20;
    cout << add(a,b) << endl;//结果为:30
    cout << add(a) << endl;//结果为:11,采用缺省
    cout << add() << endl;//结果为:3,采用缺省
    return 0;
}

函数重载:

是函数调用的灵活实现,也是多态的一种(同名函数的不同实现《执行逻辑的不同》)。

底层机制:根据不同的**参数类型,参数个数不同,与返回值无关,函数名相同**,则会在底层的程序的代码段的符号表中生成一个新的函数名,当使用不同的实参调用时,寻找匹配的函数调用。

#include <iostream>

using namespace std;

int add(int a,int b){
    return a+b;
}

float add(float a,float b){
    return a+b;
}

string add(string a,string b){
    return a+b;
}

//int add(int a,int b,int c=1){
//    return a+b;
//}//与上面的int add(int a,int b)存在二义性,不能同时存在

int main()
{
    cout << add(1,2) << endl;
    cout << add(3.14f,5.12f) << endl;
    cout << add("yao","liang") << endl;
    return 0;
}

注意:使用缺省值,注意二义性

引用(quote)

出现原因:避免程序中出现野指针的现象,因为野指针在代码维护中,很难发现问题

底层实现:类型 * const 指针变量 = &变量

#include <iostream>

using namespace std;

int add(int * const a,int * const b){
    return *a+*b;
}
int main()
{
    int a=10,b=20;
    cout << add(&a,&b) << endl;
    return 0;
}

语法形式:类型名& 引用变量 = 某个变量

#include <iostream>

using namespace std;

int add(int * const a,int * const b){
    return *a+*b;
}

int add(int& a,int& b){
    return a+b;
}

int main()
{
    int a=10,b=20;
    cout << add(&a,&b) << endl;
    cout << add(a,b) << endl;
    
    cout << "a的地址:" << &a << endl;//0x4444
    int * const c=&a;
    cout << "c的地址:" << c << endl;//0x4444
    int& c=a;//c没有自己的空间,相当于a的别名,相当于int * const &c = a;
    cout << "c的地址:" << &c << endl;//0x4444
    return 0;
}

引用优点:防止指针传址造成的不良影响,

注意:不要返回局部的返回值,引用作为函数返回值时,可以作为左值使用

#include <iostream>

using namespace std;

static int f = 100;

int& add(int& a,int& b){
    f=a+b;
    return f;
}

int main()
{
    int a=10,b=20;
    cout << add(a,b) << endl;//30
    add(a,b)=1000;
    cout << f << endl;//1000
    return 0;
}

指针与引用的对比:

#include <stdio.h>

static int *fun;

int *func(int * const a,int * const b) {
    int sum=*a+*b;
    fun=&sum;
    return fun;
}

int main(int argc, const char *argv[])
{
    /*your code*/
    int x=10,y=20;
    printf("%d\n",*func(&x,&y));
    *func(&x,&y)=100;
    printf("%d\n",*fun);
   return 0;
}

实例(数值交换):

#include <iostream>

using namespace std;

void swapfunc(int& a,int& b){
    int temp=a;
    a=b;
    b=temp;
}

int main()
{
    int x=10,y=20;
    cout << "x = " << x << ",y = " << y << endl;//x=10,y=20
    swapfunc(x,y);
    cout << "x = " << x << ",y = " << y << endl;//x=20,y=10
    return 0;
}

常引用:

#include <iostream>

using namespace std;

string func(const string & s){
//    s="yao";
    return s;
}

int main()
{
    string str="yaoliang";
    cout << "str = " << func(str) << endl;
    return 0;
}

总结:

从编译器上:

  • 引用是指针的升级

从语法形式上:

  • 引用变量是引用空间的变量别名
  • 引用引用的是一块合法的空间
  • 指针可以是野指针,十分灵活,在c++中可能会把程序写飞
  • 指针可以进行无限次的赋值
  • 引用只能赋值一次int * const a = &b; <==>int &a = b

开辟空间

在c中:

int *p=(int *)malloc(sizeof(*p));//申请空间,不初始化
memset(p,0,sizeof(*p));//初始化

升级:
int *q=(int *)calloc(0,sizeof(*q));//申请空间直接初始化

升级:
int *s=(int *)realloc(ptr,sizeof(int)*5);//给申请空间申请空间
realloc()函数将ptr所指向的内存块的大小更改为字节大小。内容将在区域的开始到新旧大小的最小值的范围内保持不变。如果新的大小大于旧的大小,则新增的内存将不会初始化。如果ptr为NULL,那么对于所有size值,调用等价于malloc(size);如果size等于零,且ptr不为NULL,则调用等价于free(ptr)。除非ptr为NULL,否则它一定是由之前对malloc()calloc()realloc()的调用返回的。如果指向的区域被移动,则执行free(ptr)操作。

failure:NULL;

cpp中:

#include <iostream>

using namespace std;

int main()
{
    int *p=new int;//malloc
    cout << *p << endl;  //单纯开辟空间,未初始化

    int *q=new int();//可在括号中指定初始化的值,calloc
    cout << *q <<endl; //开辟空间,并初始化

    int *a=new int[10]; //开辟连续的多个空间,不初始化
    cout << *a << endl;

    int *b=new int[10]();//开辟连续的多个空间,并初始化,但不可指定初始化值
    cout << *b << endl;

    int *c=new int[1000]{1,3};//开辟连续的多个空间,并指定初始化
    for(int i=0;i<1000;i++){
        cout << c[i] << " ";
    }
    cout << endl;

    //释放资源
    delete p;
    delete q;
    delete [] a;
    delete [] b;
    delete [] c;
    
    return 0;
}

new是一个函数,里面调用了malloc();delete同,所以delete和delete[]功能相同,区别在于规范

failure:throw()抛出异常,bad_alloc()

注意:

  • 在**内置函数**中,存在两步,申请与释放,所以delete与delete[]无区别,可以不规范

  • 在**自定义函数**中,new不光是开辟空间,而且在开辟空间后会调用类中的构造函数,对类对象进行初始化

    ​ delete不光是回收空间,而是在回收空间前,先对类对象进行析构,所以**必须规范使用**

img
#include <iostream>

using namespace std;

struct stu{
    string _name;
    int _age;
    //结构体或类中的构造函数
    stu(string name ,int age){
        _name=name;
        _age=age;
        cout << "含参构造"  << endl;
    }

    //开辟多个空间
    stu(){
        cout << "无参构造" << endl;
    }

    //结构体或类的析构
    ~stu(){
        cout << "析构" << endl;
    }
};

int main()
{
    stu* s=new stu("yaoliang",19);
    delete s;
    stu * ss=new stu[5];
    delete[] ss;
    return 0;
}

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

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

相关文章

UDP-A-D-乙酰氨基葡萄二钠盐;UDP-ALPHA-D-N-ACETYLGLUCOSAMINE, DISODIUM SALT

产品名称&#xff1a;UDP-A-D-乙酰氨基葡萄二钠盐 英文名称&#xff1a;UDP-ALPHA-D-N-ACETYLGLUCOSAMINE, DISODIUM SALT CAS No.&#xff1a;91183-98-1 分子式&#xff1a;C₁₇H₂₅N₃Na₂O₁₇P₂ 分子量&#xff1a;651.32 产地&#xff1a;西安 规格&#xff1a;…

如何在几百万qps的网关服务中实现灵活调度策略

作者 | 加纳斯 导读 说起百度的BFE可能不少人都听说过&#xff0c;但是其实在百度内部还有一个几百万qps的通用网关服务&#xff1a;Janus。截止当前&#xff0c;Janus服务不仅覆盖了百度内部FEED、评论、点赞、关注、直播等十多个中台服务的内网流量&#xff0c;而且为百度app…

【Java】JavaFx桌面编程整理

JavaFX是用于构建富Internet应用程序的Java库。 使用此库编写的应用程序可以跨多个平台一致地运行。 使用JavaFX开发的应用程序可以在各种设备上运行&#xff0c;例如台式计算机&#xff0c;移动电话&#xff0c;电视&#xff0c;平板电脑等。 为了开发具有丰富功能的Client Si…

运动爱好者的专属耳机,轻巧时尚又好用,哈氪无界上手

很多朋友在户外健身的时候喜欢戴上耳机&#xff0c;在音乐的节奏中去运动&#xff0c;现在市面上的运动耳机选择也特别丰富&#xff0c;为了在户外运动更安全&#xff0c;有些朋友会选择骨传导这种不入耳的耳机&#xff0c;上周我看到哈氪出了一款发带耳机&#xff0c;将运动发…

rac/rac one node扩容

某现场部署的cDAS RAC Onde Node超融合架构,2个计算/存储节点,1台仲裁节点 现网架构: 随着业务量增加,准备把仲裁节点加以利用,添加到融合节点的计算存储集群当中,与另外两个融合节点组成三节点的计算存储集群 改造后的架构: 一、配置仲裁节点(第三个计算/存储节点)…

windocs连接麒麟桌面---vnc软件

目录 一、下载vnc 二、麒麟服务器安装VNC远程 三、客户端连接 一、下载vnc客户端 Download VNC Viewer 6.22.826 - free - latest version

Nodejs -- 一文学会如何在Express中使用JWT(json web token)

文章目录在Express中使用JWT1 安装JWT相关的包2 导入JWT相关的包3 定义secret密钥4 在登录成功后生成JWT字符串5 将JWT字符串还原为JSON对象6 使用req.user获取用户信息7 捕获解析JWT失败后产生的错误8 完整代码示例在Express中使用JWT 1 安装JWT相关的包 运行如下命令&#…

Java基础概念-03-字面量

在有些资料中&#xff0c;会把字面量叫做&#xff0c;常量&#xff0c;或字面值常量&#xff0c;但最正确的叫法还是&#xff0c;字面量 小数在 Java 中也称为浮点数 下面是课本中的介绍&#xff1a; 常量是指在程序运行过程中&#xff0c;其值不能被修改的量&#xff0c;Java…

C# 移动飞机

一 实现一个飞机游戏&#xff0c;可以使用键盘控制飞机的移动。 二 游戏的显示 GameView&#xff1a;负责游戏的显示&#xff1b; 使用自定义绘制的技术&#xff0c;将飞机场地绘制出来&#xff1b; cells:3x3的单元格&#xff1b; OnSizeChanged:计算单元格的位置和大小&…

用VS软件开发“中国象棋“游戏<笔记摘录>

整体架构如上 1.很直观地去看这个中国象棋的界面,数一下它有多少行和多少列. 10行,9列:要注意这里数的是安放象棋的位置,有10行9列 这里我们首先想到的必然是二维数组,每一个行列交叉的点都设置成二维数组a[i][j]这样的格式,以此来确定棋盘上面每一个棋子的位置和走向. 我们…

01 导论【计量经济学及stata应用】

配套教材&#xff1a;《计量经济学及stata应用.陈强.2015.高等教育出版社》 官方课程链接&#xff1a;http://www.econometrics-stata.com/ 官方公众微信号&#xff1a;econometrics-stata 写博客的初衷就是为了督促自己把所学的知识进行整理和完善&#xff0c;我将于接下来的时…

性能测试-CPU性能分析,用户态us高,初步定位到代码行

监控工具安装 Grafana:安装请看我上一篇文章性能测试-JMeter influxdb grafana性能测试监控平台-食用指南_Tommy.IT的博客-CSDN博客JMeter测试脚本跑起来&#xff0c;在influxdb服务看看数据里面的数据&#xff0c;原来influxdb的jmeter库里面没有表&#xff0c;当JMeter脚本运…

PyCharm+PyQT5之三界面与逻辑的分离

之二的例程已经实现了界面与逻辑的分离,所建立的 Dialog Mainwindow 或者 widgets 等,界面改变其主调程序(暂且这样叫)更改,或者不需要大规模更改, 主调函数的程序是这样的 import sys import FistUI from PyQt5.QtWidgets import QApplication, QMainWindow,QDialog if __nam…

KubeSphere 多行日志采集方案深度探索

作者&#xff1a;大飞哥&#xff0c;视源电子运维工程师&#xff0c;KubeSphere 用户委员会广州站站长 采集落盘日志 日志采集&#xff0c;通常使用 EFK 架构&#xff0c;即 ElasticSearch,Filebeat,Kibana&#xff0c;这是在主机日志采集上非常成熟的方案&#xff0c;但在容器…

React Server Component: 混合式渲染

作者&#xff1a;谢奇璇 React 官方对 Server Comopnent 是这样介绍的: zero-bundle-size React Server Components。 这是一种实验性探索&#xff0c;但相信该探索是个未来 React 发展的方向&#xff0c;与 React Server Component 相关的周边生态正在积极的建设当中。 术语…

R语言主成分分析可视化(颜值高,很详细)

文章目录PCA特征值可视化提取变量结果变量结果可视化变量和主成分的cos2可视化变量对主成分的贡献可视化Dimension description提取样本结果样本结果可视化样本的cos2可视化样本对主成分的贡献可视化biplot参考资料网络上很多R语言教程都是基于R语言实战进行修改&#xff0c;今…

Mysql密码忘记后怎么重置密码,mysql8之后有改动

mysql8之前的修改方式&#xff1a; 1.管理员身份打开cmd&#xff1a;然后关闭mysql&#xff0c;停止MySQL服务&#xff0c;输入 net stop mysql 停止服务 2.切换到MySQL的bin文件下&#xff0c;输入mysqld --console --skip-grant-tables --shared-memory。 3上个窗口保留不要…

四种类型自编码器AutoEncoder理解及代码实现

自编码器&#xff08;AE&#xff09; 自编码器的结构和思想 结构 自编码器是一种无监督的数据压缩和数据特征表达方法。自编码器是神经网络的一种&#xff0c;经过训练后的能尝试将输入复制到输出。自编码器由编码器和解码器组成。如下图所示&#xff1a; 自编码器指的是试图…

电脑键盘功能基础知识,快速入门,抓住这份详细教程

在互联网生活发达的今天&#xff0c;电脑已经成为了学习工作的必备工具。而用来操作电脑的关键&#xff0c;就是我们经常使用的键盘和鼠标。最近有不少的小伙伴来私信小编&#xff0c;希望小编做一个电脑键盘功能基础知识介绍的详细教程。这不&#xff0c;小编应大家要求&#…

视频编解码 - RTP 与 RTCP

目录 RTP 实时传输协议 RTCP协议 将H264 RTP打包 RTP 实时传输协议 音视频数据传输&#xff0c;先将原始数据经过编码压缩后&#xff0c;将码流打包成一个个RTP包&#xff0c;再将码流传输到接收端。 打包的作用 接收端要正确地使用这些音视频编码数据&#xff0c;不仅仅需…