C++基础与深度解析 | C++初探 | Hello World | 系统I/O | 控制流 | 结构体与自定义数据类型

news2024/11/27 2:38:23

文章目录

    • 一、从Hello World谈起
    • 二、系统I/O
    • 三、控制流
    • 四、结构体与自定义数据类型

一、从Hello World谈起

#include <iostream>

void fun(const char *pInfo)
{
    std::cout << pInfo << std::endl;
}

int main()
{
    fun("Hello World!");
    fun("Hello China!");
    fun("Hello TianJin!");
}

  函数:一段能被反复调用的代码,可以接收输入,进行处理并(或)产生输出。

  • 返回类型:表示了函数返回结果的类型,可以为 void

  • 函数名:用于函数调用

  • 形参列表:表示函数接收的参数类型,可以为空,可以为 void ,可以无形参。多个形参之间用逗号分隔

  • 函数体:具体的执行逻辑

  main 函数:特殊的函数,作为整个程序的入口,系统会调用main函数

  • 返回类型:一定为 int ,表示程序的返回值,通常使用 0 来表示正常返回。0返回给操作系统

    C++标准规定:在main函数中如果没有返回语句,系统会默认返回0。

  • 函数名:C++是大小写敏感的语言,只有main函数才是系统入口函数

  • 形参列表:可以为空,可以为两个参数

    int main()
    {
        //
    }
    
    int main(int argc, char* argv[])
    {
        //
    }
    

Linux系统中获取上一个命令的退出状态,使用的命令行参数为:echo #?

  (内建)类型:为一段存储空间赋予实际的意义。

image-20240502165002825

类型并不是计算机(硬件)引入的概念,而是C++这门语言引入的概念,用于描述参数的信息。

  语句:表明了需要执行的操作。

  • 表达式+分号的语句
  • 语句块
  • if/while等语句

  注释:会被编译器忽略的内容。

  • 用于编写说明或去除不使用的语句

  • 两种注释形式:

    • /**/ :块注释

      块注释还有一个特殊的用处:

      void fun(const char* pInfo, int /*pValue*/)  //方便其他开发人员阅读
      {
          
      }
      
    • //:行注释

二、系统I/O

  系统IO指的是系统提供的输入输出接口,用于与用户进行交互。

#include <iostream>

int main()
{
    int x;
    std::cout << "How old are you: ";
    std::cin >> x;
    std::cout << "You are " << x << std::endl;
}

iostream:标准库所提供的IO接口,用于与用户交互。

  • 输入流:cin;输出流:cout / cerr / clog

  • 几个输出流之间的区别:

    • 输出目标不同

      可以将cout / cerr 这些输出流重定向到不同的文件中

    • 是否立即刷新缓冲区

      及时刷新缓冲区,可以看到一些错误信息。 cerr 会立即刷新缓冲区。 clog不立即刷新缓冲区。std::cout 不会默认立即刷新缓冲区,但你可以手动使用 std::flushstd::endl 来实现这一目的。

  • 缓冲区与缓冲区刷新:std::endlstd::flush

    • std::endl:这个操纵符不仅插入一个换行符,而且还会刷新输出流。因此,当你使用 std::endl 时,输出会立即显示,并且缓冲区会被清空。

      std::cout << "Hello, World!" << std::endl;
      
    • std::flush:这个函数可以用来强制刷新输出流,无论输出的是什么内容。如果你只是想刷新缓冲区而不插入任何额外的字符,可以使用 std::flush

      std::cout << "Hello, World!" << std::flush;
      
#include <iostream>
#include "xx.h"

#include 指令有两种形式,使用尖括号<>和双引号""

  • 使用尖括号 <>

    使用尖括号时,编译器首先会在系统的默认头文件搜索路径中查找头文件。这些默认路径由编译器的实现和操作系统决定。如果找不到,编译器可能会在用户定义的额外路径中查找。使用尖括号通常是为了包含标准库的头文件,因为这些头文件通常安装在系统的标准位置。

  • 使用双引号""

    使用双引号时,编译器首先会在包含当前文件的同一目录中查找头文件。如果当前目录中找不到,编译器会退回到系统默认的头文件搜索路径中继续查找。使用双引号通常是为了包含用户自定义的头文件或第三方库的头文件,这些文件可能位于项目的源代码目录中。

如何决定选择使用哪种形式

  • 标准库:对于标准库的头文件,推荐使用尖括号,因为它们通常不位于源代码目录中,而是安装在系统的标准位置。
  • 用户自定义头文件:对于项目特定的头文件,使用双引号可以确保编译器首先在当前目录中查找,这有助于避免潜在的冲突,并提高可移植性。

  名字空间提供了一种将程序中的实体(如变量、类型、函数等)组织在一起的方法,同时避免了命名冲突。std名字空间是C++标准库所定义的名字空间。名字空间的使用示例如下:

namespace MyNamespace {
    void foo() {
        // 函数定义
    }

    class MyClass {
        // 类定义
    };
}

int main() {
    // 使用 MyNamespace::foo() 或 MyNamespace::MyClass 来访问命名空间中的实体
    MyNamespace::foo();
    MyNamespace::MyClass myObject;
    return 0;
}

访问名字空间中元素的3种方式:

  • 域解析符::

    namespace MyNamespace {
        void foo() {
            // 函数定义
        }
    
        class MyClass {
            // 类定义
        };
    }
    
    int main() {
        // 使用 MyNamespace::foo() 或 MyNamespace::MyClass 来访问命名空间中的实体
        MyNamespace::foo();
        MyNamespace::MyClass myObject;
        return 0;
    }
    
  • using声明语句;

    为了避免在每次使用命名空间中的实体时都写完整的命名空间名称,可以使用 using 声明:

    namespace MyNamespace {
        void foo() {
            // 函数定义
        }
    
        class MyClass {
            // 类定义
        };
    }
    
    int main() {
        using namespace MyNamespace;
        // 现在可以直接使用 foo() 和 MyClass 而不需要 MyNamespace:: 前缀
        foo();
        MyClass myObject;
        return 0;
    }
    

    使用 using 声明的注意事项:

    • 使用 using 声明时要谨慎,因为它可能导致命名冲突,尤其是当多个命名空间中存在同名实体时。
    • 头文件中通常不推荐使用 using namespace,因为这会影响包含该头文件的所有源文件。
  • 名字空间别名

    C++11引入了别名声明,允许为名字空间或类型定义一个别名,使代码更简洁:

    namespace MyNamespace {
        void foo() {
            // 函数定义
        }
    
        class MyClass {
            // 类定义
        };
    }
    
    int main() {
        namespace MyNS = MyNamespace;
        MyNS::foo(); // 使用别名访问函数
        return 0;
    }
    

  名字空间与名称改编(name mangling),这是每一个编译器都会有的行为。

liujie@liujie-vm:~/Documents/demo/HelloWorld/Debug$ nm main.cpp.o
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
0000000000000062 t _GLOBAL__sub_I__ZN10NameSpace13funEv
000000000000000e T main
0000000000000019 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 B _ZN10NameSpace11xE
0000000000000000 T _ZN10NameSpace13funEv
0000000000000007 T _ZN10NameSpace23funEv
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
0000000000000000 r _ZStL19piecewise_construct
0000000000000004 b _ZStL8__ioinit
 
liujie@liujie-vm:~/Documents/demo/HelloWorld/Debug$ nm main.cpp.o | c++filt -t
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
0000000000000062 unsigned short _GLOBAL__sub_I__ZN10NameSpace13funEv
000000000000000e T main
0000000000000019 unsigned short __static_initialization_and_destruction_0(int, int)
0000000000000000 B NameSpace1::x
0000000000000000 T NameSpace1::fun()
0000000000000007 T NameSpace2::fun()
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
0000000000000000 r std::piecewise_construct
0000000000000004 bool std::__ioinit

注意

  • 在Linux系统中,nm 是一个命令行工具,用于列出目标文件(通常是 .o 文件)中的符号(symbol)。这些符号可以是函数、变量、常量等。nm 命令对于调试和分析程序的符号表非常有用。

    基本的 nm 命令用法示例:

    nm yourfile.o
    

    nm 的输出通常包含三列:

    1. 符号类型:可以是 T(文本)、D(数据)、B(bss)、R(只读数据)、C(常量)等,这些表示符号所在的内存段。
    2. 符号地址:符号在内存中的地址。
    3. 符号名称:符号的名称
  • c++filt 是一个用于解码 C++ 符号的命令行工具。它主要用于将 C++ 符号(通常是经过 mangling(名称修饰)后的)转换为可读的源代码形式。在 C++ 中,为了支持函数重载和复杂的类型系统,编译器会对函数和变量的名称进行 mangling,以生成唯一的标识符。

    c++filt 的使用非常简单,你只需要将 mangled 名称作为参数传递给该工具,它就会输出对应的 demangled(解码后)名称。

    • 基本用法:

      c++filt [options] [mangled_name]
      
    • -t 选项:

      c++filt-t 选项用于输出解码后的类型信息。当你使用 -t 选项时,c++filt 不仅会解码函数名,还会尝试解码参数和返回值的类型。

  C / C++ 系统IO比较:

  • printf: 使用直观,但容易出错
  • cout: 不容易出错,但书写冗长

在C++20格式化库中,提供了新的解决方案: std::format,它提供了一种类似于 Python 的字符串格式化机制,但编译器对C++20格式化库的支持还不够,需要 C++20 兼容的编译器。

三、控制流

  以猜数字为例,

#include <iostream>

int main()
{
    std::cout << "Please Input a number: \n";
    
    int y = 0;
    std::cin >> y;
    if(y == 42)
    {
        std::cout << "You are right!\n";
    }
    else
    {
        std::cout << "You are wrong!\n";
    }
}

  if语句用于分支选择,条件部分用于判断是否执行,返回bool值。语句部分是要执行的操作。

image-20240502195006090
#include <iostream>

int main()
{
    int x = 42, y = 0;
    
    while (x != y)
    {
        std::cout << "Please Input a number: ";
        std::cin >> y;
        if(y == 42)
        {
            std::cout << "You are right!\n";
        }
        else
        {
            std::cout << "You are wrong!\n";
        }
    }    
}

  while语句用于循环执行,条件部分用于判断是否执行。语句部分是要执行的操作。

image-20240502195609717

== 与= 操作

  • =操作:用于赋值,将数值保存在变量所对应的内存中,赋值表达式的返回值为左侧的常量。

    int x;
    x = y = 42;
    
  • ==操作:用于判断两个值是否相等

可以将常量放在==左边以防止误用。

四、结构体与自定义数据类型

  在C++中,结构体(struct)是一种复合数据类型,它允许将不同的数据项组合成一个单一的实体。结构体在C++中有着广泛的应用,包括表示数据集合、实现数据封装以及作为函数参数传递等。

  • 定义结构体

    结构体可以通过以下方式定义:

    struct MyStruct {
        int a;
        double b;
        std::string c;
        // 默认构造函数
        MyStruct() : a(0), b(0.0), c("") {}
    
        // 带有两个参数的构造函数
        MyStruct(int ia, double ib) : a(ia), b(ib), c("Initialized") {}
    
        // 全参构造函数
        MyStruct(int ia, double ib, const std::string& ic) : a(ia), b(ib), c(ic) {}
    };
    
  • 初始化结构体

    结构体可以通过直接初始化或使用构造函数进行初始化,结构体的构造函数与结构体的名称相同,并且没有返回类型。

    // 直接初始化
    MyStruct ms = {10, 20.5, "Hello"};
    
    // 使用构造函数(如果定义了)
    MyStruct ms(10, 20.5, "Hello");
    
  • 使用结构体

    结构体定义了一组数据,可以通过点(.)操作符访问这些数据:

    ms.a = 42;
    std::cout << ms.b << std::endl;
    
  • 结构体与类的区别

    尽管结构体和类在C++中非常相似,但它们之间存在一些差异:

    • 默认访问权限:在C++中,结构体成员的默认访问权限是public,而类的默认访问权限也是public,但在C++11及以后的版本中,结构体和类都可以通过访问说明符明确指定成员的访问权限。
    • 数据封装:类通常用于数据封装,而结构体更倾向于表示数据的简单集合。
    • 继承:类可以用于实现继承,而结构体通常不用于继承。
  • 结构体与函数

    结构体可以作为函数的参数传递,也可以作为函数的返回值:

    void printStruct(const MyStruct& ms) {
        std::cout << "a: " << ms.a << ", b: " << ms.b << ", c: " << ms.c << std::endl;
    }
    
    MyStruct createStruct() {
        return {1, 2.5, "Example"};
    }
    
  • 匿名结构体:

    C++允许在定义结构体的同时实例化,而不需要先声明类型:

    auto myStructInstance = struct {
        int a;
        double b;
        std::string c;
    } {10, 20.5, "Hello"};
    
  • 嵌套结构体

    结构体可以嵌套在其他结构体中:

    struct OuterStruct {
        struct InnerStruct {
            int x;
            double y;
        };
        InnerStruct inner;
    };
    
  • 结构体字面量

    C++11引入了结构体字面量,允许直接创建结构体的实例:

    auto ms = MyStruct{10, 20.5, "Hello"};
    

  结构体(struct)在C++中不仅可以包含数据成员,还可以引入成员函数,从而更好地表示函数与数据的相关性。

在结构体中定义成员函数

struct MyStruct {
    int value;

    // 构造函数
    MyStruct(int v) : value(v) {}

    // 成员函数,用于获取当前值
    int getValue() const {
        return value;
    }

    // 成员函数,用于设置新值
    void setValue(int v) {
        value = v;
    }
};

使用成员函数

  创建结构体对象后,可以通过点(.)操作符调用其成员函数:

MyStruct obj(10);
int val = obj.getValue(); // 调用成员函数获取值
obj.setValue(20);         // 调用成员函数设置新值

通过引入成员函数,结构体可以隐藏内部实现细节,只通过成员函数暴露操作数据的方式。

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

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

相关文章

从 Oracle 到 TiDB,国有大行打造本地生活 APP 新体验

导读 本文介绍了某国有大行推出的本地生活服务类 APP 在数字时代的创新应用实践。该 APP 利用金融科技和互联网平台模式&#xff0c;打造“金融非金融”的线上生态服务平台&#xff0c;满足了用户多样化的生活需求。为应对用户增长和数据量增加带来的挑战&#xff0c;该 APP 决…

【网络编程】Servlet的前后端练习 | 表白墙 | 前后端交互 | 提交消息 | 获取消息

文章目录 一、Servlet的前后端练习1.表白墙服务器要实现的逻辑&#xff1a;1.获取消息 &#xff1a;2.提交消息&#xff1a;完整前端代码&#xff1a;完整后端代码&#xff1a; 一、Servlet的前后端练习 1.表白墙 服务器要实现的逻辑&#xff1a; 1.页面加载时&#xff0c;网…

47-Qt控件详解:Buttons Containers1

一 QPushButton (命令按钮) #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QPushButton>//引入QPushButton类对应的头文件class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWind…

YOLOv8独家原创改进: AKConv(可改变核卷积)

1.AKConv原理介绍 地址:2311.11587 (arxiv.org) 摘要:基于卷积运算的神经网络在深度学习领域取得了令人瞩目的成果,但标准卷积运算存在两个固有的缺陷。一方面,卷积运算仅限于局部窗口,无法捕获其他位置的信息, 并且它的采样形状是固定的。 另一方面,卷积核的大小固定为…

vue3土味情话pinia可以持久保存再次修改App样式

我是不是你最疼爱的人-失去爱的城市 <template><div class"talk"><button click"getLoveTalk">土味情话</button><ul><li v-for"talk in talkStore.talkList" :key"talk.id">{{ talk.title }}<…

HarmonyOS开发案例:【UIAbility内和UIAbility间页面的跳转】

UIAbility内和UIAbility间页面的跳转&#xff08;ArkTS&#xff09; 介绍 基于Stage模型下的UIAbility开发&#xff0c;实现UIAbility内和UIAbility间页面的跳转。包含如下功能&#xff1a; UIAbility内页面的跳转。跳转到指定UIAbility的首页。跳转到指定UIAbility的指定页…

AtCoder Regular Contest 177 D. Earthquakes(概率 单调栈)

题目 D - Earthquakes 思路来源 官方题解 题解 对于不存在连锁反应的区间&#xff0c;每个区间独立处理&#xff0c;最后求个乘积 对于每个区间&#xff0c;相邻的两个杆子距离都小于H&#xff0c; 意味着没倒的区间是个连续的区间&#xff0c;假设要算i的概率 一定是第i…

软考144-下午题-【试题三】:UML图-类图、用例图

一、分值与目标 题型&#xff1a; 问题一~问题三&#xff08;扩展/UML——>设计模式&#xff09; 二、UML基础知识回顾 2-1、关系 UML中有四种关系&#xff1a;依赖、关联、泛化、实现。 1、关联 关联是一种结构关系&#xff0c;它描述了一组链&#xff0c;链是对象之间的…

Uniapp 自定义弹窗

布局 <view><view v-if"show" class"popup"><view class"popup-box"><view>支付方式:{{way}}</view><view>停车费用:{{money}}</view><view class"btn-box"><view class"ca…

修改el-checkbox样式

一定要在最外层&#xff1b; //未选中框/deep/ .el-checkbox__inner{border-color: #0862a3;}//选中框/deep/ .el-checkbox__input.is-checked .el-checkbox__inner{background-color: #0862a3;border-color: #0862a3;}//未选中框时右侧文字/deep/ .el-checkbox__label{}//选中…

虚拟化技术 挂载iSCSI网络存储器

一、实验内容 挂载iSCSI网络存储器到ESXi主机 二、实验主要仪器设备及材料 安装有64位Windows操作系统的台式电脑或笔记本电脑&#xff0c;建议4C8G或以上配置已安装vSphere Client 三、实验步骤 1、挂载iSCSI网络存储器到ESXi主机 配置ESXi主机的虚拟网络 ESXi识别出三块…

【补充】图神经网络前传——DeepWalk

论文阅读 论文&#xff1a;https://arxiv.org/pdf/1403.6652 参考&#xff1a;【论文逐句精读】DeepWalk&#xff0c;随机游走实现图向量嵌入&#xff0c;自然语言处理与图的首次融合_随机游走图嵌入-CSDN博客 abstract DeepWalk是干什么的&#xff1a;在一个网络中学习顶点…

039——解决室内不能使用GPS问题

目录 引入 GUI整改 client添加GPS分析 完善服务器网络通讯部分代码 添加GPS的BSW层 GPS操作部分代码&#xff08;相当于驱动&#xff09; 效果展示 项目管理操作 引入 最近在写论文加上出去玩了一圈所以停更了一段时间。上次咱们GPS有个室内用不了的问题&#xff0c;咱…

Ubuntu 24 换国内源及原理 (阿里源 清华源 中科大源 网易源)

备份原文件 sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak 编辑源文件 sudo gedit /etc/apt/sources.list.d/ubuntu.sources 粘贴到文本&#xff08;其中一个即可&#xff09;&#xff1a; &#xff08;阿里源&#xff09…

与 Apollo 共创生态:Apollo 七周年大会带我体会自动驾驶技术的发展

前言 自动驾驶技术作为当今科技领域的热门话题&#xff0c;吸引着无数开发者和企业的目光。而在这个风起云涌的行业中&#xff0c;Apollo开放平台作为自动驾驶领域的领军者之一&#xff0c;扮演着不可或缺的角色。七年前&#xff0c;当Apollo开放平台刚刚起步时&#xff0c;也…

C语言(指针)5

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

等保一体机能过三级等保吗?过等保无需再买安全设备如何做到?

等保一体机能过三级等保吗&#xff1f;过等保无需再买安全设备如何做到&#xff1f; 全云在线 2024-03-28 12:08 广东 尽管等保建设的标准是统一的&#xff0c;但由于不同行业和用户规模的差异&#xff0c;建设方案呈现出多样化的特点。 虽然重点行业过等保现象确实已经十分…

【35分钟掌握金融风控策略25】定额策略实战2

目录 基于收入和负债的定额策略 确定托底额度和盖帽额度 确定基础额度 基于客户风险评级确定风险系数 计算最终授信额度 确定授信有效期 基于收入和负债的定额策略 在实际生产中&#xff0c;客户的收入和负债数据大多无法直接获得&#xff0c;对于个人的收入和负债数据&…

中小型客户过等保,选择比努力重要!

国内谈网络安全&#xff0c;等保是绕不过去的话题。 作为国家网络安全保障的基本制度、基本策略、基本方法&#xff0c;等保经过十几年发展&#xff0c;其基本概念、相关标准已经深入人心&#xff0c;市面上各类成熟的等保方案让用户应接不暇&#xff0c;挑花了眼。 网络安全…

数据结构之排序(上)

片头 嗨&#xff0c;小伙伴们&#xff0c;大家好&#xff01;我们今天来学习数据结构之排序&#xff08;上&#xff09;&#xff0c;今天我们先讲一讲3个排序&#xff0c;分别是直接插入排序、冒泡排序以及希尔排序。 1. 排序的概念及其应用 1.1 排序的概念 排序&#xff1a…