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

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 {};

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】预处理详解(上卷)

前言 预处理也是C语言中非常重要的存在。那么就详细地来了解一下吧。 预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 1 __FILE__ //进行编译的源文件 2 __LINE__ //文件当前的…

LabVIEW硬件与仿真双模式设计液压系统

在实际项目中&#xff0c;结合LabVIEW与液压运动控制器&#xff0c;通过设计两种运行方式&#xff1a;硬件运行和仿真运行&#xff0c;使得系统既能进行实际操作又能进行仿真测试。此设计不仅方便了开发调试&#xff0c;也为教学培训和展示提供了极大的便利。本文将从项目背景、…

手把手AI实战(一)治愈系动画视频

手把手AI实战(一)治愈系动画视频 一、成果展示 二、步骤拆解 2.1 AI出图 可以使用你顺手的AI绘图工具&#xff0c;国外的像Midjouney、Stable Diffusion&#xff0c;国内的像扣子、智普清言等等。我这里用了剪映的&#xff0c;地址是&#xff1a;https://jimeng.jianying.com/a…

【AI论文与新生技术】Follow-Your-Emoji:精细可控且富有表现力的自由式人像动画技术

我们提出了 Follow-Your-Emoji&#xff0c;这是一种基于扩散的肖像动画框架&#xff0c;它使用目标地标序列对参考肖像进行动画处理。肖像动画的主要挑战是保留参考肖像的身份并将目标表情转移到该肖像&#xff0c;同时保持时间一致性和保真度。为了应对这些挑战&#xff0c;Fo…

C++11 列表初始化(initializer_list),pair

1. {} 初始化 C98 中&#xff0c;允许使用 {} 对数组进行初始化。 int arr[3] { 0, 1, 2 };C11 扩大了 {} 初始化 的使用范围&#xff0c;使其可用于所有内置类型和自定义类型。 struct Date {int _year;int _month;int _day;Date(int year, int month, int day):_year(year…

梯度下降: 02. 批量梯度下降BGD,随机梯度下降SGD,小批量梯度下降MBGD

简介 本文从原理上介绍了三种梯度下降的方法,相同点,异同点,优缺点。 内容包含了数学公式的推导与说明 1. 梯度下降的3种方法 梯度下降分三类,原理基本相同,操作方式略有区别 批量梯度下降BGD(BatchGradient Descent):使用全量数据进行特征抽取,模型训练小批量梯度下降…

tkinter颜色选择器

tkinter颜色选择器 颜色选择器效果代码 颜色选择器 Tkinter 提供了一个简单易用的颜色选择器模块 colorchooser&#xff0c;通过调用 colorchooser.askcolor() 方法&#xff0c;我们可以轻松实现颜色选择功能。 效果 代码 import tkinter as tk from tkinter import colorch…

启动xv6遇坑记录

我是在VMware上的Ubuntu22.04.4搭建的&#xff0c;启动xv6遇到超多bug&#xff0c;搞了好几天&#xff0c;所以记录一下。 目录 git push的时候报错 make qemu缺少包 运行make qemu时卡住 可能有影响的主机设置 git push的时候报错 remote: Support for password authent…

Soildworks学习笔记(二)

放样凸台基体&#xff1a; 自动生成连接两个物体两个面的基体&#xff1a; 2.旋转切除&#xff1a; 3.剪切实体&#xff1a; 4.转换实体引用&#xff1a; 将实体的轮廓线转换至当前草图使其成为当前草图的图元,主要用于在同一平面或另一个坐标中制作草图实体或其尺寸的副本。 …

【Redis学习笔记05】Jedis客户端(string、list、set)

Jedis客户端 1. 命令 1.1 String类型 1.1.1 常见命令 SET命令 语法&#xff1a;SET key value [EX seconds | PX milliseconds] [NX|XX] 说明&#xff1a;将string类型的value值设置到指定key中&#xff0c;如果之前该key存在&#xff0c;则会覆盖原先的值&#xff0c;原先…

MyBatis二级缓存开启条件

MyBatis缓存为俩层体系。分为一级缓存和二级缓存。 一级缓存&#xff1a; 一级缓存默认开启&#xff0c;一级缓存的作用域是SqlSession级别的&#xff0c;这意味着当你更换SqlSession之后就不能再利用原来的SqlSession的一级缓存了。不同的SqlSession之间的一级缓存是隔离的。…

如何确保redis缓存中的数据与数据库一致

一、双写模式&#xff1a; 在写入数据库时&#xff0c;也写入缓存。 二&#xff1a;失效模式&#xff1a; 在写入新数据后&#xff0c;删除缓存中数据&#xff0c;下次请求时查询数据库&#xff0c;并把查到的最新数据写入缓存。 不管是双写模式还是失效模式&#xff0c;缓…

网页中生成ZIP文件,Zip 压缩、解压技术在 HTML5 浏览器中的应用

JSZip 是一款可以创建、读取、修改 .zip 文件的 javaScript 工具。在 web 应用中&#xff0c;免不了需要从 web 服务器中获取资源&#xff0c;如果可以将所有的资源都合并到一个 .zip 文件中&#xff0c;这时候只需要做一次请求&#xff0c;这样既减少了服务器的压力&#xff0…

每日题库:Huawe数通HCIA——15(30道)

注&#xff1a;由于限制原因&#xff0c;今后资料仅提供给粉丝 所有资料均来源自网络&#xff0c;但个人亲测有效&#xff0c;特来分享&#xff0c;希望各位能拿到好成绩&#xff01; PS&#xff1a;别忘了一件三连哈&#xff01; 今日题库&#xff1a; 231. 如下图所示的网…

OceanBase 4.3 特性解析:列存技术

在涉及大规模数据的复杂分析或即时查询时&#xff0c;列式存储是支撑业务负载的关键技术之一。相较于传统的行式存储&#xff0c;列式存储采用了不同的数据文件组织方式&#xff0c;它将表中的数据以列为单位进行物理排列。这种存储模式允许在分析过程中&#xff0c;查询计算仅…

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

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

GDPU unity游戏开发 寻路与导航

学会寻路&#xff0c;出门在外&#xff0c;身份不是他给的&#xff0c;他做不了你一直的导航。 角色寻路 角色控制器替换为普通的角色控制器&#xff0c;给实验九的地形增加NavMesh Surface组件&#xff0c;然后给角色增加NavMesh Agent组件&#xff0c;并选择合适的参数。通过…

mac安装brew遇到的一些问题

mac终端执行命令/bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)”&#xff0c;无法建立连接或连接超时错误&#xff0c;错误信息如下&#xff1a; curl: (28) Failed to connect to raw.githubusercontent.com port 443 af…

高性能MySQL(第3版)电子书笔记

Mysql官方文档&#xff1a;https://dev.mysql.com/doc/refman/5.7/en/ 高性能MySQL&#xff08;第3版&#xff09;&#xff1a;百度网盘&#xff0c;基于Mysql5.1和Mysql5.5 本机版本 mysql> select version(); ------------ | version() | ------------ | 5.7.32-log |…

Numba 的 CUDA 示例(4/4):原子和互斥

本教程为 Numba CUDA 示例 第 4 部分。 本系列第 4 部分总结了使用 Python 从头开始学习 CUDA 编程的旅程 介绍 在本系列的前三部分&#xff08;第 1 部分&#xff0c;第 2 部分&#xff0c;第 3 部分&#xff09;中&#xff0c;我们介绍了 CUDA 开发的大部分基础知识&#xf…