c++visualStudio学习笔记

news2025/1/20 5:59:25

文章目录

  • 5 c++如何工作
    • 5.1include
    • 5.2main
    • 5.3 <<
    • 5.3 linker链接器
  • 7 C++链接器linker是如何工作的
    • 7.1案例
  • 10 头函数
    • 10.1案例
    • 10.2头文件
    • 10.3pragma once
  • 34const
    • 34.1 常数
    • 34.2指针
    • 34.3类和方法
    • 34.4引用
    • 34.5mutable

5 c++如何工作

源文件就是文本文件转化到可执行的二进制文件或者程序,然后源文件会传到编译器,然后编译成二进制文件(binary)

 #include<iostream>

int main()
{
	std::cout << "hello world " << std::endl;
	std::cin.get();
}

5.1include

首先这其中· #include称为预处理文件,任何以#开始都是预处理文件,当编译器收到一个源文件时,它第一件事就是预处理你所有的预处理指令。这就是为啥·叫预处理,因为整的发生在编译之前。
这里用include,include就是找到一个文件,这里是找一个叫iostream,该文件里所有内容会被复制到目前这个文件里。
你include的文件被称为头文件,我们之所有include头文件iostream是因为我们需要一个函数(function):cout的申明。cout可以打印东西到控制台console,然后我们有了这个main函数,main函数相当重要。

5.2main

main函数被称作入口点(entry point)也就是说我们运行程序时,计算机会从该函数里的代码开始执行。
这其中main的定义是int,然而我们没有返回一个整数(integer)。
这是因为main是个例外,你不需要从主函数返回任何类型的值,如果你不返回任何值,它会返回0,这只适合于main函数

5.3 <<

在这里插入图片描述
这些向左的带角的括号,看起来像左移位符号(bit shift),其实是被重载的符号,你得把它想成一个函数,我知道他看起来像运算符,但实际上,运算符就是函数,所以这种情况下和cout.print一模一样
这里目的即使把hello world 传入 cout,cout把它打印在控制台里。然后传入endl,end line告诉控制台前进到另一行。

5.3 linker链接器

1首先 include iostream,即使预处理,会在编译文件之前被评估。即使把iostream中内容拷贝到这个文件里。
2当我们头文件被评估后,我们的文件会被编译,这个阶段,编译器会把我们的c++转化成实际的机器码。
所有cpp文件都会被编译,而头文件不会,只有cpp,头文件在预处理被include到头文件里,那是他们被编译的时候,所以我们有一堆cpp文件被编译,而且它们是一个个被单独被编译的。每个cpp文件会被编译成一个object文件,如果扩展名的话,用Windows编译器是.obj,当有了一个个obj时候,也就是cpp被编译过后的结果,我们得有办法把他们联系起来,组成exe。这时我们得朋友linker(链接器)就有用武之地
你可以在linker标签下看它的设定,但基本就是把所有obj拿来的然后联系起来
linker的作用是把所有obj连成exe,
error list 的工作原理是,解析(parse)output窗口,找error关键字,然后从哪找信息,放入list,功能简单,output功能比较全面
在这里插入图片描述
此处双击问题即可到发生错误的地方。
当你单独编译一个文件,linking显然不会发生,因为你单独一个文件。
如果我们有多个c++文件呢?
假设我们有打印hello world 到控制台,但不想用cout,用自己的logging函数,这就需要包装logging函数

我们来写log函数,会接受cstring作为参数,取名,message,并打印message到控制台。
在这里插入图片描述
此时我们可以把log放到另一个文件
在这里插入图片描述
新建一个log.cpp会发现cout不是STD的member,这基本上说不懂cout是啥,这要是没有吧cout声明include进来。
c++中每个symbo都需要某种声明,cout是main里include文件里定义的一个函数,也就是iostream
把#include剪切入log.cpp再次编译成功了
回到main我想调用log函数,ctrl+f7编译失败,不知道cin,加入#include,会发现log还是找不到,我们把函数从一个文件移动到另一个。
发生错误的原因是它识别不出log,所以我们需要通过一个声明(declaration)来解决。声明从字面意思,就是声明log是一个存在的东西。有点像承诺,告诉编译器有一个函数叫log,编译器就真的相信了。因为编译器根本不关心resolving(解析)log到底被哪定义的。
这里有两个词,declaration(声明)和definition(定义)申明就是这个symbol真的存在,定义是说这个函数到底是什么,这个函数的主体。

这中间有个疑问,如何能确定有这个函数,这时候link就有用了。
当我们文件被编译后,linker就会去找log的定义,然后跟我们main里调用联系起来。
如果找不到定义,就会得到linker error
在这里插入图片描述
我们可以看到两个obj因为,每个编译cpp都会产生obj,然后linker会串成exe

7 C++链接器linker是如何工作的

linking是从c++源码到二进制可执行文件的一个过程。
我们编译后会通过一个叫做链接的过程,链接的主要工作是找到每个符号和符号的位置并把它们链接在一起。
我们需要一种方法将这些文件链接到一个程序。即使没有外部文件里的函数,比如你已经把一个程序写在一个文件里了。应用程序仍需要知道入口点在哪里

7.1案例

在vs中我们有一个非常简单的项目,只包含一个源文件math.cpp.
在这里有两个函数log和multiply,multiply实际上调用了log函数,打印出multiply这个单词到控制台。然后返回a*b
在这里插入图片描述
编译有两个阶段-编译和链接。
你可以对其进行区分,如果你按ctrl-F7或者按下编译按钮,只有编译会发生链接完全不会发生。然而如果你build你的项目或者按F5运行它会编译然后链接。
如果你按crl+f7可以发现没发生任何错误
如果你按build会发现得到一个链接错误,缺少入口函数,我们的主函数。
因为我们的编译分为两个阶段,如果编译中出现错误,错误会以c开头,如c243.
如果链接中出现问题会以LNK开头
你在文件的属性,可以知道配置类型是exe,exe必须要有一个入口点。
在这里插入图片描述
在这里插入图片描述
在一个文件中即可build成功。
如果这些函数存在多个文件中。如把log函数加入log.cpp中,再执行会报错,因为找不到名为log的函数
在这里插入图片描述
所以把声明加入math.cpp中可以发现
在这里插入图片描述
编译成功

10 头函数

在C++基础上,头文件传统上是用来申明某些函数类型,以便用于整个程序中。在链接器章节中我们知道,为了让我们知道函数和类型的存在,我们需要某种声明。
我们需要一个共同的地方存放函数声明,只是声明,没有实际的定义,没有函数的主体。

10.1案例

假设在主文件生成一个c++文件定义了Log函数
main.cpp

#include <iostream>
void Log(const char* message)
{
	std::cout<<message<<std::endl;
}
int main()
{
	std::cout<<"hello world "<<std::endl;
	std::cin.get();
}

在log.cpp中
在这里插入图片描述
在这里还有一个log.cpp中使用了Log函数,我们拿到一个错误,log函数不再该文件中,该文件不知道log函数的存在。我们在main中可以正常使用,在log.cpp中会报错。所以log.cpp到底需要沙漠才不会报错。
如何才能告诉它,log函数存在,只是区别于别的地方。
这时是函数申明的使用之地。
在这里插入图片描述
加入函数声明后可以正常使用按ctrl+f7可以编译。对项目编译也可以看到链接成功,因为可以找到log函数。
我们告诉了log.cpp那个函数存在某处,如果我们创建另外一个文件呢?我们创建一个别的文件,然后使用这个log函数呢?
这意味这个void log声明可以到处复制黏贴吗?
答案是的,你确实需要怎么做,但是有一个方法可以让一切简单一点。
就是头文件

10.2头文件

头文件一般被include到cpp文件里面,基本就是复制和黏贴进cpp文件里。我们创建一个头文件,上图中的文件夹都是过滤器并不是真正的文件夹。我们可以在资源文件下创建一个头文件。其实就是无论在什么地方创建头文件都没关系
在这里插入图片描述
在这里插入图片描述
此时我们将头文件剪切放在这里。我们的头文件log.h,我么可以在任何想用log函数的地方include它,然后显然他会帮我们做哪些我们不想人工做的事。
其实我们还可以include“log.h”到main.cpp,main.cpp包含实际的函数定义,所以我们并不需要它,我们反正可以调用log。但加进去也不会报错。

如果我们在main中调用initLog会报错所以我们需要去log头文件把函数签名加进去。

void Log(const char* message);
void initLog();

此时可以在main中调用

10.3pragma once

在这里插入图片描述
pragma once意思是只include这个文件一次,是一种头文件保护符
他所作的是防止我们把单个头文件多次include到一个单一翻译单元中。
其实不会防止我们把头文件include到程序各处,只防止到一个翻译单元里,也就是一个单独的cpp文件,原因是我们不小心把一个文件多次include到一个翻译单元中。我们会得到一个重复的错误,因为我们会多次复制和黏贴那个头文件。一个比较好的办法是我们创建一个Struct
在这里插入图片描述
我们可以创建一个struct player{},如果我们把这个文件,两次应付得到一个翻译单元,并且没有头文件保护。他会真的include这个文件两次,也就是我们会有两个structs,他们有相同的名字player。
如果我们去掉#pragma once 并如下图引入两次Log.h。
在这里插入图片描述
我们会得到一个player structure重复定义的问题。
也许会觉得自己不会干这个种事,但是c++种会出现套娃的问题。
比如有一个头文件player include log,然后player 又被inlude到其他文件。假如我们创建一个common也包含log.h。如下图把pragam once 注释掉
在这里插入图片描述
在这里插入图片描述
此时main中也会出现同样问题。
如果log.h不再一个文件夹中,比如它目前存在log.cpp的上一级目录中,可以使用…/来返回上一级目录
在这里插入图片描述
iostream“”也可以用来告诉编译器位置,可以在任何地方用,我们可以把iostream换成引号,将完全没有问题。所以方括号只用于编译器include路径,引号用于所有。但我一般只喜欢将它用于相对位置,还不如方括号。

34const

const基本就是做出承诺,承诺某些东西是不变的。
它只是一个可以绕开的承诺,你可以绕开承诺
这个承诺好处是可以简化很多代码

34.1 常数

在这里插入图片描述
这里是无法改变的,做出承诺从语法上说这个整数是一个常数

34.2指针

当你声明一个指针,没有用const会在堆上生成,这里我可以做两件事,逆向引用a,然后将它设为一个值比如2,然后我们可以做另一件事就是重新分配实际的指针,这样他就指向别的地方,比如&MAX_AGE为了绕开const限制
这里我们可以做两件事,我们可以改变指针内容,我们也可以改变指向的地址
在这里插入图片描述

在这里插入图片描述
1const 放在*前
不能修改指针指向内容
在这里插入图片描述

const int* a=new int

这里尝试改变a指向内容会发生错误,当改变a本身是不会报错的
2 const放在*后
在这里插入图片描述
我可以改变a的指向内容,但我不能把实际指针本身重新赋值,指向别的东西
这两个效果是一样的,关键是 * 前还是 * 后
在这里插入图片描述
3 *前后都有
在这里插入图片描述
不能改变a的指向内容,也不能把实际指针本身重新赋值,指向别的东西

34.3类和方法

放在函数名后
在这里插入图片描述
在这里插入图片描述

这个方法不会修改任何实际类,我们不能修改类成员变量
不能再setter中用函数名后的const,这样我们不能修改类中的成员变量,通常用在GetX中
在这里插入图片描述
如果m_x是一个指针,想让它保持不变,这样会写三个const,这意味着返回了一个不能被修改的指针,指针内容也不能被修改,这个方法承诺不修改类中变量

在这里插入图片描述

34.4引用

在这里插入图片描述

引用没有指针本身和指向内容的区别了,因为引用就是内容
如果把const去掉会报错,因为无法确定GetX函数不会写入Entity类,有时候会写两个GetX一个带const,一个不带

在这里插入图片描述

34.5mutable

当函数为const,但你有些调试的参数可以用mutable。
mutable允许函数是常量方法,但可以修改变量
在这里插入图片描述

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

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

相关文章

MySQL自增主键一定是连续的吗

测试环境&#xff1a; MySQL版本&#xff1a;8.0 数据库表&#xff1a;T &#xff08;主键id&#xff0c;唯一索引c&#xff0c;普通字段d&#xff09; 如果你的业务设计依赖于自增主键的连续性&#xff0c;这个设计假设自增主键是连续的。但实际上&#xff0c;这样的假设是错…

一个大二计算机学生的学期总结(2022末年)

学期总结前言一、本学期的自我反思&#xff08;1&#xff09;返校之前在家期间练习题黑马头条教学管理平台Ajax练习仿写JD&#xff08;2&#xff09;返校之后在学校期间练习题本学期课程hbase、hive、Hadoop一直奉行的话前言 ☀️东流逝水&#xff0c;叶落纷纷&#xff0c;荏苒…

初级程序员 中级程序员 高级程序员级别划分

网络上众说纷纭&#xff0c;大都站立在对某一技术的知识掌握量上来界定&#xff0c;或者有些人说着说着&#xff0c;发现无法自圆其说&#xff0c;然后就说这三种人就是一种叫法&#xff0c;你觉得你是高级你就高级了&#xff0c;从概念上讲&#xff0c;这三者之间必然有质的区…

20221221查看RK3588开发板的LCD屏幕的分辨率(1536x2048)

20221221查看RK3588开发板的LCD屏幕的分辨率 2022/12/21 18:46 方法一&#xff1a;adb/串口 console:/ $ console:/ $ [ 37.217258][ T57] vbus5v0_typec: disabling [ 37.217707][ T57] vcc3v3_pcie20: disabling console:/ $ console:/ $ console:/ $ dumpsys wi…

我国输配电及控制设备行业现状及竞争分析 营收及企业规模整体增长

根据观研报告网发布的《中国输配电设备行业发展趋势研究与未来投资分析报告&#xff08;2022-2029年&#xff09;》显示&#xff0c;输配电及控制设备主要应用于电力系统和下游用电企业的电能传输和电能控制等&#xff0c;直接影响电网的建设、安全与可靠运行&#xff0c;输配电…

Go:使用 go-micro 构建微服务(二)

1. 什么是go micro# 1.1 go micro作用 它是一个可插入的RPC框架&#xff0c;用于在Go中编写微服务。开箱即用&#xff0c;您将收到&#xff1a; 服务发现: 应用程序自动注册到服务发现系统负载平衡: 客户端负载平衡&#xff0c;用于平衡服务实例之间的请求同步通信: 提供请求…

12月21日:fastadmin顶部搜索栏selectpage事件绑定以及实现添加表单和查询数据在同一个页面

fastadmin将添加表单从弹窗转为页面 如图所示&#xff0c;实现这种两个标签页&#xff0c;各自执行自己的操作 添加页从弹窗转为页面实现步骤&#xff1a; 首先&#xff1a;从前端页面来看&#xff0c;需要将添加的功能移动到index页面&#xff0c;即可初步实现 将Index页面如…

l2实时接口在手机APP上的使用方法介绍

考虑到很多人白天只能在手机上看行情&#xff0c;因此也重点介绍一下l2实时接口在手机APP上的使用方法&#xff0c;但是功能上PC才是最直观的。除了本文介绍的重点功能&#xff0c;Level2还有其他功能&#xff0c;具体使用方法可参考同花顺官方介绍。 利用“BBD”看当天大盘走…

R语言中的风险价值模型度量指标TVaR与VaR

99&#xff05;的预期缺口[…]与99.6&#xff05;的[…]风险值非常接近 受到“ 瑞士经验”报告中一句话的启发&#xff0c; 在99&#xff05;置信水平[...]上的预期缺口[…]对应于大约99.6&#xff05;至99.8&#xff05;的风险价值 最近我们被客户要求撰写关于VaR的研究报告…

DPDK KNI 接口3

图1. kni结构图 从结构图中可以看到KNI需要内核模块的支持&#xff0c;即rte_kni.ko 当rte_kni模块加载时&#xff0c;创建/dev/kni设备节点&#xff08;rte_kni模块创建kni杂项设备&#xff0c;文件系统节点/dev/kni需要手动或者通过udev机制创建&#xff09;&#xff0c;藉…

django.test.client的一些用法

对于文件&#xff08;文本文件&#xff0c;或图片文件等等文件&#xff09;从客户端上传到服务端&#xff0c;对于常规情况&#xff0c;也就是真实服务端和客户端&#xff0c;我们往往是需要给files这个参数的。 具体来说&#xff0c;就像这样&#xff1a; import requestshe…

万字总结Bootloader到内核的启动流程

Bootloader启动流程分析 Bootloader的启动过程可以分为单阶段、多阶段两种。通常多阶段的 Bootloader能提供更为复杂的功能以及更好的可移植性。从固态存储设备上启动的 Bootloader大多都是两阶段的启动过程。第一阶段使用汇编来实现&#xff0c;它完成一些依赖于CPU体系结构的…

【ML实验5】SVM(手写数字识别、核方法)

实验代码获取 github repo 山东大学机器学习课程资源索引 实验目的 实验内容 这里并不是通过 KTT 条件转化&#xff0c;而是对偶问题和原问题为强对偶关系&#xff0c;可以通过 KTT 条件进行化简。 令 xα[α1,α2,...,αn]Tx\alpha[\alpha_1,\alpha_2,...,\alpha_n]^Txα[α1…

极狐阿尔法S 全新HI版在上海率先推送城区NCA

继深圳之后&#xff0c;12月19日&#xff0c;极狐阿尔法S 全新HI版城区NCA&#xff08;即城区智驾导航辅助功能&#xff09;交付上海车主&#xff0c;将胜任城区复杂环境的“点到点”智驾融入更多用户的生活中。 此前&#xff0c;极狐阿尔法S 全新HI版已面向全国车主推送第二次…

Unreal Engine项目目录结构

目录 Engine 引擎源码文件 Games 项目工程文件 Visualizer VS编辑器配置文件 之前说的是工程目录结构&#xff0c;这次来说项目目录结构。 这里只是举了个例子&#xff0c;实际请根据不同的UE版本自行分析。 Engine 引擎源码文件 虚幻是开源的&#xff0c;我们可以直接在工…

05-Golang的基本数据类型

Golang的基本数据类型变量数据类型整型类型基本使用及细节基本介绍整数类型演示案例整型的使用细节浮点类型基本使用及细节基本介绍浮点型的分类案例演示使用细节字符类型基本使用及细节基本介绍案例演示字符类型本质探讨布尔类型的使用基本介绍字符串类型基本使用及细节基本介…

复变函数的积分

复变函数的积分化解成曲线积分的问题。 那化成第一类曲线积分还是第二类曲线积分&#xff1f;&#xff08;高等数学 中有讲第一类曲线积分和第二类曲线积分&#xff09;。 路径是有方向的&#xff0c;由起点和终点不同&#xff0c;路径有正向和负向。 复变函数的积分归结起来…

「学习方法」Scratch、Python、C++如何学才能融会贯通?

前言 相信很多家长朋友都发现一个问题&#xff1a;“编程教育正在以飞快的速度渗透于孩子们的培养体系中&#xff0c;这是为什么呢&#xff1f;原因很简单&#xff0c;这是因为通过专业的编程教育可以全面提升孩子的逻辑思维、创造力、动手能力等&#xff0c;让孩子们拥有更全…

线程池的使用

线程池 3大方法、7大参数、4种拒绝策略 好处&#xff1a;降低资源的消耗、提高响应的速度、方便管理、 线程池可以理解为银行业务 三大方法 第1大方法&#xff1a;单个线程 ExecutorService threadExecutor Executors.newSingleThreadExecutor(); 第2大方法&a…

c语言 操作符详解例题 数据存储 指针初阶 水仙花数 杨辉三角 逆序字符串 喝汽水问题 打印图形 猜凶手

【题目名称】 下面代码的结果是&#xff1a;a #include <stdio.h> int i; int main() {i--; sizeof的返回值是无符号整型if (i > sizeof(i)) i四个字节所以是4。算出的结果类型是unsigned int无符号和有符号比较大小 会先把有符号整型转化为无符号。 -1放到内…