C++基础问题

掌握形参默认带缺省值的函数

函数调用时

#include <iostream>int sum(int a, int b = 20) {return a + b;
}int main() {int a = 10, b = 20;int ret = sum(a, b);cout << "ret: " << ret << endl;ret = sum(a);/*a 使用默认值压栈: 时压入 a 的值和 20.push 14Hmov ecx, dowrd ptr[ebp - 4]push ecxcall sum*/ret = sum();// 压入 10 和 20.
}

总的来说,函数效率有所增长:减少一次 push 指令。

带有缺省的函数的声明

// 一个缺省只能被声明一次,并且只能被从右向左声明
#if 1    // 编译通过
int sum(int a = 10, int b = 20);
#elif    // 报错: 默认值只能给一次
int sum(int a = 10, int b = 20);
int sum(int a, int b = 20);
#elif    // 编译通过
int sum(int a, int b = 20);
int sum(int a = 10, int b);
#endifint main() {int a = 10, b = 20;int ret = sum(a, b);cout << "ret: " << ret << endl;ret = sum(a);/*a 使用默认值压栈: 时压入 a 的值和 20.push 14Hmov ecx, dowrd ptr[ebp - 4]push ecxcall sum*/ret = sum();// 压入 10 和 20.
}int sum(int a, int b) {return a + b;
}

掌握内联函数

内联函数和普通函数的区别?

  • 内联函数:在编译过程中没有函数调用的开销,因为在函数的调用点函数被直接展开处理。
  • 内联函数将不再产生相应的函数符号。
  • 函数定义时加上inline并不一定会让函数变成内联函数,仅仅是对编译器的一种建议。如递归很可能不会被处理为内联函数。
#include <iostream>using namespace std;#define IS_INLINE   1#if IS_INLINE
inline 
#endifint sum(int a, int b = 20) {return a + b;
}int main() {int a = 10, b = 20;int ret = sum(a, b);// 此处有标准的函数调用过程// 当函数调用的开销的占比过高,建议使用内联函数cout << "ret: " << ret << endl;}

注意:inline 在 debug 版本上是不起作用的。

验证:inline 在 release 版能出现

chipen@ubuntu:~/code/inlineTest$ cat main.cpp
#include <iostream>using namespace std;int sum(int a, int b) {return a + b;}int main() {int a = 10, b = 20;int ret = sum(a, b);return 0;}
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O2
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text    0000000000000000 .text
0000000000000000 l    d  .text.startup    0000000000000000 .text.startup
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000 g     F .text    0000000000000008 _Z3sumii    # sum 函数的符号
0000000000000000 g     F .text.startup    0000000000000007 mainchipen@ubuntu:~/code/inlineTest$ vim main.cpp    # 给 sum 函数加上 inline
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O2
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text.startup    0000000000000000 .text.startup
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000 g     F .text.startup    0000000000000007 main
# 可见,添加内联以后,sum 函数不再有对应的符号,而是被直接替换
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O0
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text    0000000000000000 .text
0000000000000000 l    d  .text._Z3sumii    0000000000000000 .text._Z3sumii
0000000000000000 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedIjEE
0000000000000001 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedImEE
0000000000000002 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedIyEE
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000  w    F .text._Z3sumii    0000000000000018 _Z3sumii
0000000000000000 g     F .text    0000000000000033 main
# 在只用 -O0 的低优化等级时,inline 需求依然被忽略,可见 inline 只是一种建议行为

函数重载

chipen@ubuntu:~/code/inlineTest$ cat test01.cpp 
#include <iostream>
#include <cstring>using namespace std;bool compare(int a, int b) {cout << "int, int" << endl;return a > b;
}bool compare(double a, double b) {cout << "double, double" << endl;return a > b;
}bool compare(const char *a, const char *b) {cout << "const char*, const char*" << endl;return strcmp(a, b) > 0;
} int main() {compare(10, 20);compare(10.0, 20.0);compare("hello", "world");return 0;
}
chipen@ubuntu:~/code/inlineTest$ ./test01 
int, int
double, double
const char*, const char*

注意1: 一组重载函数指的是: 在同一作用域下的, 函数名相同作用域不同的函数

如当尝试在 main 函数中添加如下声明

chipen@ubuntu:~/code/inlineTest$ cat test01.cpp 
#include <iostream>
#include <cstring>using namespace std;bool compare(int a, int b) {cout << "int, int" << endl;return a > b;
}bool compare(double a, double b) {cout << "double, double" << endl;return a > b;
}bool compare(const char *a, const char *b) {cout << "const char*, const char*" << endl;return strcmp(a, b) > 0;
} int main() {bool compare(int a, int b);compare(10, 20);compare(10.0, 20.0);compare("hello", "world");return 0;
}
chipen@ubuntu:~/code/inlineTest$ g++ test01.cpp -o test01
test01.cpp: In function ‘int main()’:
test01.cpp:26:17: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]26 |         compare("hello", "world");|                 ^~~~~~~|                 ||                 const char*
test01.cpp:23:26: note:   initializing argument 1 of ‘bool compare(int, int)23 |         bool compare(int a, int b);|                      ~~~~^
test01.cpp:26:26: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]26 |         compare("hello", "world");|                          ^~~~~~~|                          ||                          const char*
test01.cpp:23:33: note:   initializing argument 2 of ‘bool compare(int, int)23 |         bool compare(int a, int b);|                             ~~~~^

注意2:同一类型,加不加const在编译器眼中没有区别。

void func(int a) {}
void func(const int a) {}
// 报错void func(int *a) {}
void func(const int *a) {}
// 编译通过void func(int *a) {}
void func(int const *a) {}
// 报错

为什么 C++ 支持函数重载,C 语言不支持函数重载?

在对符号表中函数命名时,C++采取了更能准确描述一个函数的命名方式,而 C 语言直接用函数名字作为符号名。

因此,C 和 C++ 中的函数由于函数名不同,不能直接调用,会在链接时发生无法解析的外部符号的错误,因为在符号表中找不到对应的函数符号名。

要实现 C 和 C++ 之间都可以调用的函数,应该这样定义

#ifdef __cplusplus
extern "C" {
#endif
int sum(int a, int b) {return a + b;
}
#ifdef __cplusplus
}
#endif

掌握const的用法

基本理解:const 修饰的常变量不能作为左值使用。
常变量 != 常量,例如:

chipen@ubuntu:~/code/inlineTest$ cat test02.cpp 
#include <cstdio>int main() {const int a = 20;int *p = (int *)&a;*p = 30;printf("%d %d %d\n", a, *p, *(&a));return 0;        
}
chipen@ubuntu:~/code/inlineTest$ ./test02
20 30 30

这是个不可思议的现象。原因是:在编译器的前端阶段,a 被认为是不可能被修改的,故在后文中被做了直接替换,但是 *p, *(&a) 要求必须访问内存,故得到了 20 30 30。

证明这是一种优化行为:

chipen@ubuntu:~/code/inlineTest$ cat test02.cpp 
#include <cstdio>int main() {volatile const int a = 20;    # 不让编译器优化 aint *p = (int *)&a;*p = 30;printf("%d %d %d\n", a, *p, *(&a));return 0;        
}
chipen@ubuntu:~/code/inlineTest$ ./test02
30 30 30    # 符合预期

const修饰的量常出现的错误是:

  • 常量不能再作为左值 <= 直接修改常量的值
  • 不能把常量的地址泄露给一个普通的指针或者普通的引用变量 <= 可能间接修改常量的值

const和一级指针的结合:(const修饰的是离它最近的类型)

  • const int * p -> 指针指向的变量不能修改
  • int const * p -> 同上
  • int *const p -> 指针本身不能修改
  • const int *const p -> 指针本身和指针所指的变量都不能修改
int a = 10;            
int *p1 = &a;            // 通过, 无类型转换
const int *p2 = &a;        // 隐式类型转换
int *const p3 = &a;        // 隐式类型转换
const int b = 10;
int *p4 = &b;            // 不通过, (const int *) -> (int *)
const int *p5 = &b;        // 通过
int *const p6 = &b;        // 不通过, (const int *) -> (int *const)// 总结: 权限只能缩小不能扩大

const和二级/多级指针的结合

int a = 20;
int *p = &a;
const int **p1 = &p;
// 典型错误,这样赋值会让原来的普通指针 p 指向被 const 修饰的变量
/*
正确写法:
int a = 20;
const int *p = &a;
cosnt int **p1 = &p;
*/int *const *p2 = &p;
int **const p3 = &p;

左值引用和右值引用

int main() {int a = 10;    // 左值,有地址有名字,值可以修改int &b = a;int &&c = 20;    // 20 为右值,没内存,没名字c = 30// 右值引用可以修改const int &b = 20;/*int temp = 20;temp -> b*/const int &d = 20;return 0;
}

右值引用:

  • int &&c = 20;专门用来引用右值类型,指令上可以自动产生临时量,然后直接引用临时量。

  • 右值引用变量本身是一个左值,只能用左值引用来引用它。

  • 不能用一个右值引用变量引用一个左值。

const、指针和引用的结合应用

int main() {// 写一句代码,在内存的 0x0018ff44 处写一个 4 字节的 10int *p = (int *)0x0018ff44;int *&&p = (int *)0x0018ff44;int *const &p = (int *)0x0018ff44;return 0;
}

深入理解 c++ 的 new 和 delete

new 和 delete 为C++ 的运算符

malloc 和 free 为 C 的库函数

开辟内存失败时:

  • malloc 需要返回值与 nullptr 比较,为空时失败。

  • new 会抛异常。

new 有多少种?

int *p1 = new int(20);
int *p2 = new (nothrow) int;
int *p3 = new const int(40);// 定位 new
int data = 0;
int *p4 = new (&data) int(50);
cout << "data: " << data << endl;    // 输出 data: 0

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

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

相关文章

AI PPT探秘

—— 序言 ——AI时代已经深入到我们的生活、工作之中&#xff0c;AI不会淘汰所有的人&#xff0c;但会淘汰不会用AI的人&#xff0c;让AI处理执行&#xff0c;你专注决策&#xff01;—— 典型的四步AI PPT过程 ——AI PPT四步&#xff1a;内容——>排版——>美化——&g…

Gin Web 服务集成 Consul:从服务注册到服务发现实践指南(下)

在微服务架构中&#xff0c;Web 层作为系统的入口门面&#xff0c;承担着请求路由、权限校验和服务聚合等核心功能。本文将围绕 Gin 框架与 Consul 注册中心的集成展开&#xff0c;详细讲解 Web 服务如何实现服务注册与发现&#xff0c;帮助你构建可扩展的微服务前端架构。 承接…

PDF 的开发工具库: Adobe PDF Library

Adobe PDF Library 是 Adobe 公司提供的一个软件开发工具包(SDK)&#xff0c;它本质上是 Adobe Acrobat 的"无界面"版本&#xff0c;但功能更为强大。作为 PDF 处理领域的专业解决方案&#xff0c;它为开发者提供了创建、操作和管理 PDF 文档的全面能力。 #mermaid-s…

dubbo源码学习2-dubbo协议源码分析

协议(Protocol)的概念 协议(Protocol)是指在计算机通信或网络交互中&#xff0c;双方事先约定好的规则和标准&#xff0c;用于规范数据如何打包、传输、接收和解释。 所以简单说就是规则&#xff0c;发送数据编码的规则&#xff0c;接收数据解码的规则 Dubbo中的协议 在Dubbo…

麒麟信安联合申威:共筑安全高效的自主计算新生态

为深化长三角区域先进技术产业协同创新&#xff0c;推动集成电路领域技术需求对接&#xff0c;6月26日“集成电路领域产业技术需求对接一申威生态成果分享”专题活动举行。本次活动聚焦国产化全栈能力建设&#xff0c;重点发布申威产品与生态的最新进展&#xff0c;促成“芯片-…

裸仓库 + Git Bash 搭建 本地 Git 服务端与客户端

下面是在 Windows 上使用 裸仓库 Git Bash 搭建 本地 Git 服务端与客户端 的详细步骤。适合本机或局域网其他设备通过 SSH 或本地路径 访问&#xff0c;简单轻量&#xff0c;适合开发者日常使用或小团队协作。 &#x1f6e0;️ 一、准备工作 1. 安装 Git for Windows 默认安装…

AI文档智能体上线!AutoHub v0.7.0 全面升级,重构知识工作流

AI文档智能体上线&#xff01;AutoHub v0.7.0 全面升级&#xff0c;重构知识工作流 如何让每一个知识工作者都像专家一样高效&#xff1f; 这正是 OpenCSG AutoHub 想解决的问题。 无论你是产品经理、项目负责人、运维工程师&#xff0c;还是企业管理者&#xff0c;日常都要…

SpringMVC参数接收与数据返回详解

一&#xff0c;参数的接收参数接收的几种方式&#xff1a;1.使用servlet API接收参数在方法参数中添加HttpServletRequest类型的参数&#xff0c;然后就可以像servlet的方法一样来接收参数 RequestMapping("p1")public String param1(HttpServletRequest request){St…

OpenCV 人脸分析----人脸识别的一个经典类cv::face::EigenFaceRecognizer

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 这是基于 PCA&#xff08;主成分分析&#xff09; 的人脸识别算法实现。它通过将人脸图像投影到一个低维的“特征脸”空间中进行识别&#xff0c…

RESTful风格

带着问题&#xff0c;找答案&#xff1a; 通过本片文章&#xff0c;你会了解以下四点。并且我会给出go语言的实现案例。 1、了解restful风格的来源、起源、演变史 2、了解restful风格的定义、含义 3、掌握restful风格的简单运用 4、做一个小demo 在restful中前进&#xf…

了解GC吗?什么是GC?

GC是什么&#xff1f;为什么要GC&#xff1f; GC&#xff08; Garbage Collection &#xff09;&#xff0c;垃圾回收&#xff0c;是Java与C的主要区别之一。作为Java开发者&#xff0c;一般不需要专门编写内存回收和垃圾清理代码。这是因为在Java虚拟机中&#xff0c;存在自动…

FDMA读写AXI BRAM交互:FPGA高速数据传输的核心技术

在图像处理系统中,当1080P视频流以每秒60帧的速度传输时,传统DMA每帧会浪费27%的带宽在地址管理上——而FDMA技术能将这些损失降至3%以内 现代FPGA系统中,高效数据搬运往往是性能瓶颈的关键所在。当你在手机上流畅播放4K视频、在自动驾驶系统中实时处理激光雷达点云时,背后…

独立开发A/B测试实用教程

A/B测试&#xff08;A/B Testing&#xff09;&#xff0c;又称分组测试、对照实验&#xff0c;是产品开发和运营中提升转化率、优化用户体验的常用方法。无论你是做App、SaaS、网站还是小程序&#xff0c;合理地利用A/B测试&#xff0c;都能帮助你用数据驱动决策&#xff0c;让…

如何将iPhone备份到Mac/MacBook

许多iPhone用户非常重视备份&#xff0c;但在Mac上选择合适的备份方法可能会令人困惑。市场上有各种各样的备份工具&#xff0c;找到一个既易于使用又能保存所有重要数据&#xff08;如照片、视频、消息、WhatsApp聊天记录和联系人&#xff09;的工具至关重要。如果你正在寻找一…

Logseq 插件开发实战四:发布到官方插件市场

&#x1f6a9;系列回顾 初识插件机制并实现自动压缩粘贴的图片国际化 I18N 与配置多语言自定义斜线命令 SlashCommand发布到官方插件市场 开源地址&#xff1a;logseq-plugin-image-tiny&#xff0c;欢迎来⭐。 &#x1f41e; 插件上线问题记录 问题描述 本地插件开发完成后…

[netty5: ByteToMessageCodec MessageToByteEncoder ByteToMessageDecoder]-源码分析

ByteToMessageCodec ByteToMessageCodec 是一个结合了 ByteToMessageDecoder 和 MessageToByteEncoder 的编解码器&#xff0c;可以实时地将字节流编码或解码为消息&#xff0c;反之亦然。 public abstract class ByteToMessageCodec<I> extends ChannelHandlerAdapter {…

Ubuntu20.04安装mujoco210, mujoco-py时的报错处理

参考 Ubantu 20.04 安装 Mujoco210、mujoco-py、gym及报错解决 安装 mujoco210 创建 .mujoco 文件夹 mkdir ~/.mujoco亲测必须是 .mujoco 文件夹&#xff0c;不然会报错&#xff01; 下载 mujoco210-linux-x86_64.tar.gz 并解压到 .mujoco 文件夹 mojoco下载地址 测试 mojo…

全志T507 音频ALSA核心层注册流程分析

一.ALSA核心层注册流程分析 驱动目录&#xff1a;kernel-4.9/sound/core/sound.c struct file_operations snd_fops {.owner THIS_MODULE,.open snd_open, (inode, file)---->struct snd_minor *mptr snd_minors[minor];---->file->f_op fops_get(mptr->f_ops…

评论区实现 前端Vue

根据后端部分定义评论区功能实现 golang后端部分-CSDN博客&#xff0c;重点需要实现三个部分&#xff0c;1.当前用户发起新根评论请求&#xff1b;2.评论区展示部分&#xff1b;3.某一根评论的子评论展示以及回复组件显示。 整体流程解释 数据从后端接收&#xff0c;整体在in…

差分定位技术:原理、分类与应用场景

文章目录 简介基本概念位置差分伪距差分载波相位 差分定位技术精密单点定位&#xff08;PPP&#xff09;差分全球定位系统&#xff08;DGPS&#xff09;实时动态定位&#xff08;RTK&#xff09; 应用场景总结 简介 差分定位&#xff08;Differential Positioning&#xff09;是…