C++中的一些困惑(长期更新中)

news2024/12/25 0:47:00

C++中的一些困惑

文章目录

  • C++中的一些困惑
    • 1. using std::具体命名与using namespace std;
    • 2. 【int \*p[10] 】与 【int (\*p)[10]】
    • 3. main()函数可带参,参从何来?
    • 4. constexpr函数的返回值可不为常量,那这时constexpr关键字作用是什么?
    • 5.为什么C++ STL不提供任何“树”容器?
    • 6. 函数参数后面的`const`

这是个人笔记,记录一些学习过程中没有理解以及容易混淆的问题与解答

1. using std::具体命名与using namespace std;

在C++中,使用 usingusing namespace 都是用来简化代码中命名空间的写法,但它们有不同的影响和使用场景,各有优劣:

  1. using std::具体命名
    • 优势:精确导入了命名空间中的特定名称,可以避免命名冲突,提高代码的可读性和可维护性。
    • 劣势:需要逐个导入每个需要使用的名称,可能会显得冗长,尤其是当需要导入多个名称时。
cppCopy codeusing std::vector;
using std::cout;
using std::endl;

int main() {
    vector<int> nums = {1, 2, 3};
    cout << "Hello, world!" << endl;
    return 0;
}
  1. using namespace std;
    • 优势:一次性导入了整个 std 命名空间中的所有名称,可以方便地使用标准库中的各种功能,节省了代码中重复写命名空间的时间和空间。
    • 劣势:可能会引入命名冲突,尤其是当在代码中使用了其他命名空间或自定义了相同名称的变量或函数时,容易导致代码混乱和不可预测的行为。
cppCopy codeusing namespace std;

int main() {
    vector<int> nums = {1, 2, 3};
    cout << "Hello, world!" << endl;
    return 0;
}

总体来说:推荐使用 using std::具体的类型 的方式来导入特定的名称,因为它可以明确指定要导入的内容,避免了潜在的命名冲突问题,同时保持了代码的清晰性和可维护性。而在大型项目或者有多个命名空间交叉的情况下,最好避免使用 using namespace std; 这样的全局命名空间导入方式,以免引起不必要的麻烦。

2. 【int *p[10] 】与 【int (*p)[10]】

  1. int *p[10]
    • 这表示 p 是一个数组,包含了 10 个元素。
    • 每个元素都是一个指向 int 类型的指针。
    • 可以直接通过索引来访问数组中的指针,如 p[0] 表示数组的第一个指针。
int *p[10];  // p 是一个数组,包含了 10 个指向 int 的指针
  1. int (*p)[10]
    • 这表示 p 是一个指针,指向一个包含 10 个整数的数组。
    • p 指向的整个数组是一个单独的对象,而不是一个指向指针的数组。
    • 需要通过解引用来访问指针指向的数组元素,如 (*p)[0] 表示指针 p 所指向数组的第一个元素。
int (*p)[10];  // p 是一个指针,指向一个包含 10 个整数的数组

举个例子来比较两者的使用:

int main() {
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    int *p1[10];  // 数组,包含 10 个指向 int 的指针
    p1[0] = arr;  // 将数组 arr 的首地址赋给 p1 的第一个指针

    int (*p2)[10];  // 指针,指向包含 10 个整数的数组
    p2 = &arr;  // 将数组 arr 的地址赋给 p2

    // 使用 p1 访问数组元素
    for (int i = 0; i < 10; ++i) {
        std::cout << *(p1[0] + i) << " ";  // 输出数组元素
    }

    std::cout << std::endl;

    // 使用 p2 访问数组元素
    for (int i = 0; i < 10; ++i) {
        std::cout << (*p2)[i] << " ";  // 输出数组元素
    }

    return 0;
}

在上面的例子中,p1 是一个数组,包含了 10 个指向 int 的指针,而 p2 是一个指针,指向一个包含 10 个整数的数组。这两者的使用方式略有不同,因为 p1 中的每个元素都是指针,而 p2 指向的是整个数组对象。

3. main()函数可带参,参从何来?

在 C++ 中,main 函数可以具有带参数的形式,这些参数通常用于接收命令行参数。这些参数是由操作系统在程序启动时传递给程序的,并且可以在 main 函数的参数列表中接收到。

标准的 main 函数的声明有两种形式:

int main()

或者

int main(int argc, char* argv[])

第一种形式是不带参数的,程序启动时不会接收任何命令行参数。第二种形式是带参数的,其中 argc 表示命令行参数的数量,argv 是一个指向字符指针数组的指针,每个指针指向一个命令行参数的字符串。

  • argc(argument count)表示命令行参数的数量,包括程序名称在内。
  • argv(argument vector)是一个指针数组,每个元素指向一个命令行参数的字符串,其中 argv[0] 通常是程序的名称,argv[1]argv[2] 等依次是传递给程序的其他命令行参数。

例如,以下是一个简单的示例:

#include <iostream>
#include <string>

// 编写一个带实参的main函数并运行
int main(int argc, char* argv[]) {
    // 确保有足够的实参
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " <arg1> <arg2>" << std::endl;
        return 1;  // 返回非零值表示错误退出
    }

    // 将实参连接成一个字符串
    std::string result = std::string(argv[1]) + " " + std::string(argv[2]);

    // 输出连接后的字符串
    std::cout << "Concatenated string: " << result << std::endl;

    return 0;
}

在VS code中编译运行:

  1. 打开Terminal,使用命令行编译源文件

    g++ -o  生成的程序名(如:myprogram)  源文件.cpp
    
  2. 编译器会生成一个名为myprogram的可执行文件

  3. 在终端运行程序并传参

    ./myprogram hello world
    

执行过程及结果:

image-20240313204143778

4. constexpr函数的返回值可不为常量,那这时constexpr关键字作用是什么?

虽然constexpr函数的返回值并非总是常量,但使用constexpr关键字可以告诉编译器,希望在可能的情况下在编译期间进行求值和优化。这样可以使代码更加灵活并提高性能,特别是在一些需要进行编译期间计算的场景下,constexpr函数非常有用。

进一步解释:

  • 某些场景下,函数的返回值仍然可以再编译期间确定。(通常是因为函数的输入参数是常量表达式,或者函数内部只包含了可以在编译期间计算的操作),如:
#include <iostream>

// constexpr函数,参数是常量表达式
constexpr int add(int a, int b) {
    return a + b;
}

int main() {
    // 在编译期间就可以计算出结果
    // 因为输入参数是常量表达式 
    constexpr int result = add(10, 20);

    std::cout << "Result: " << result << std::endl;
    return 0;
}

5.为什么C++ STL不提供任何“树”容器?

一个讨论:https://www.codenong.com/205945/

6. 函数参数后面的const

void func() const {};

是常量成员函数,即在函数内部不会修改对象的成员变量。
endl;
return 0;
}


## 5.为什么C++ STL不提供任何“树”容器?

一个讨论:https://www.codenong.com/205945/

## 6. 函数参数后面的`const`

```cpp
void func() const {};

是常量成员函数,即在函数内部不会修改对象的成员变量。

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

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

相关文章

Mybatis03-ResultMap及分页

1、属性名和字段名不一致问题 1.问题 数据库中的字段 新建一个项目Mybatis-04&#xff0c;拷贝之前&#xff0c;测试实体类字段不一致的情况 public class User {private int id;private String name;private String password; }select * from mybatis.user where id #{id} …

计算机网络 ——网络层(IPv4地址)

计算机网络 ——网络层&#xff08;IPv4地址&#xff09; 什么是IPv4地址IP地址的分类特殊的IP地址 查看自己的IPv4地址 我们今天来看IPv4地址&#xff1a; 什么是IPv4地址 IPv4&#xff08;Internet Protocol version 4&#xff09;是第四版互联网协议&#xff0c;是第一个被…

【YOLO系列】YOLOv1学习(PyTorch)原理加代码

论文网址&#xff1a;https://arxiv.org/pdf/1506.02640 训练集博客链接&#xff1a;目标检测实战篇1——数据集介绍(PASCAL VOC&#xff0c;MS COCO)-CSDN博客 代码文件&#xff1a;在我资源里&#xff0c;但是好像还在审核&#xff0c;大家可以先可以&#xff0c;如果没有的…

二分【1】二分查找框架 查找指定元素

目录 二分查找 基本思想 几种情况汇总 一。严格递增序列 1.查找本身 2.查找第一个大于等于自己的 3.查找第一个大于自己的 4.严格递减序列 二。有重复元素 1.取其中第一个出现的 2.取其中最后一个出现的 二分查找 基本思想 几种情况汇总 一。严格递增序列 1.查找本身…

Vitis HLS 学习笔记--接口存储器布局模型

目录 1. 简介 2. 详解 2.1 数据对齐 2.2 数据结构填充 3. 总结 1. 简介 软件开发者写的程序会在 CPU 处理器上运行&#xff0c;而硬件开发者设计的“内核”则会在 FPGA 上运行。这两部分需要通过一个精心设计的接口来沟通&#xff0c;就像两个人用对讲机来交流一样。为了…

Java | Leetcode Java题解之第140题单词拆分II

题目&#xff1a; 题解&#xff1a; class Solution {public List<String> wordBreak(String s, List<String> wordDict) {Map<Integer, List<List<String>>> map new HashMap<Integer, List<List<String>>>();List<List…

16_ Vue.js高级指南:条件渲染、列表渲染与数据双向绑定

文章目录 1. 条件渲染v-if2. 列表渲染v-for3. 数据双项绑定v-model4. 计算属性Appendix 1. 条件渲染v-if v-if标签直接接收函数或boolean类型变量 v-if 为true&#xff0c;则当前元素会进入到dom树v-else会自动执行 前方v-if的取反操作 v-show v-show值为true则值展示值不展示…

Qt基于SQLite数据库的增删查改demo

一、效果展示 在Qt创建如图UI界面&#xff0c;主要包括“查询”、“添加”、“删除”、“更新”&#xff0c;四个功能模块。 查询&#xff1a;从数据库中查找所有数据的所有内容&#xff0c;并显示在左边的QListWidget控件上。 添加&#xff1a;在右边的QLineEdit标签上输入需…

C++ | Leetcode C++题解之第139题单词拆分

题目&#xff1a; 题解&#xff1a; class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {auto wordDictSet unordered_set <string> ();for (auto word: wordDict) {wordDictSet.insert(word);}auto dp vector <bool> (s.…

HC-05蓝牙模块配置连接和使用

文章目录 1. 前期准备 2. 进入AT模式 3. 电脑串口配置 4. 配置过程 5. 主从机蓝牙连接 6. 蓝牙模块HC-05和电脑连接 1. 前期准备 首先需要准备一个USB转TTL连接器&#xff0c;电脑安装一个串口助手&#xff0c;然后按照下面的连接方式将其相连。 VCCVCCGNDGNDRXDTXDTXD…

jquery.datetimepicker控件不弹出的问题

项目场景&#xff1a; CRM项目&#xff0c;在项目中涉及日期类输入框&#xff0c;打算采用平常见到的点击选择日期的方式。在浏览了网页后&#xff0c;目前比较好的解决方案是jquery.datetimepicker和flatpicker两种&#xff0c;flatpicker的缺点是官网是英文版的&#xff0c;…

计算机系统基础笔记(12)——控制

前言 在持续输出ing 一、条件码 1.处理器状态&#xff08;x86-64&#xff0c;部分的&#xff09; 当前程序的执行信息 ◼ 临时数据 ◼ 运行时栈的位置&#xff08;栈顶&#xff09; ◼ 当前代码控制点的位置&#xff08;即将要执行的指令地址&#xff09; ◼ 最近一次指令执…

SpringCloudAlibaba基础二 Nacos注册中心

一 什么是 Nacos 官方&#xff1a;一个更易于构建云原生应用的动态服务发现(Nacos Discovery )、服务配置(Nacos Config)和服务管理平台。 集 注册中心配置中心服务管理 平台。 Nacos 的关键特性包括: 服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理 …

进军rust:从0开始学习rust语法

一.变量类型 Rust语言中的基础数据类型有以下几种&#xff1a; 1.整数型 整数型简称整型&#xff0c;按照比特位的长度和有无符号位可以分为以下几种 isize和usize两种整数类型是用来衡量数据大小的&#xff0c;它们的位长度取决于所运行的目标平台&#xff0c;如果是32位架…

openpose标定中棋盘格检测错误的解决方案

文章目录 1、openpose 棋盘格检测流程2、解决过程3、实测结果1、openpose 棋盘格检测流程 在opencv中通过调用cv::findChessboardCorners()函数,同时指定棋盘格内角点尺寸来检测画面中的棋盘格,结果将以一定顺序来保存结果。通常指定尺寸的两个纬度的值不能相同,例如当指定…

学习笔记——路由网络基础——等开销负载均衡

3、等开销负载均衡 等开销负载均衡&#xff1a;到达同一目标网段&#xff0c;存在多条路由条目&#xff0c;存在两条或两条以上的路由优先级值和开销值都是最优的(优先级值和开销值一致)&#xff0c;则这几条路径执行负载均衡(在ping中就是这条路由发个包再下一条路由再发个包…

计算机网络 —— 网络层(子网掩码和子网划分)

计算机网络 —— 网络层&#xff08;子网掩码和子网划分&#xff09; 网络地址转换NAT子网掩码和子网划分举个例子第一步&#xff1a;看类型第二步&#xff1a;从主机号开始比对第三步&#xff1a;去头去尾 我们今天来看子网掩码和子网划分&#xff1a; 网络地址转换NAT 网络…

[FSCTF 2023]Tea_apk

得到密文和密钥 import base64 from ctypes import c_uint32import libnumDELTA 0x9E3779B9def decrypt(v, n, k):rounds 6 int(52 / n)sum c_uint32(rounds * DELTA)y v[0].valuewhile rounds > 0:e (sum.value >> 2) & 3p n - 1while p > 0:z v[p …

使用缓存降低数据库并发读写方案探索

文章目录 前言缓存设计思想缓存划分缓存应用时机 客户端缓存浏览器缓存网关或代理服务器缓存CDNPCDN 服务端缓存本地缓存本地缓存实现Java堆缓存memcached/ecachecaffeineORM框架一级/二级缓存 分布式缓存分布式缓存优缺点分布式缓存实现分布式缓存实施过程可能遇到问题分布式缓…

【冲刺秋招,许愿offer】第 一 天

【冲刺秋招&#xff0c;许愿offer】第 一 天 知识点emo环节 知识点 Java Leetcode&#xff1a;可以用LinkedListMap模拟实现LRUCache&#xff0c;用hash表查找&#xff0c;双向链表记录顺序。集合&#xff1a;集合的遍历方式&#xff0c;可以使用迭代器(万能)、增强for只能用…