C++入门基础

文章目录

  • C++核心特性详解(基础增强版)
    • 一、第一个C++程序:Hello World
      • 完整代码解析
      • 新手常见问题
    • 二、命名空间(详解版)
      • 1. 为什么需要命名空间?
      • 2. 命名空间使用场景
      • 3. 嵌套命名空间
      • 4. 匿名命名空间
    • 三、输入输出系统(深度解析)
      • 1. 输入输出对比
      • 2. 格式化输出
      • 3. 输入注意事项
    • 四、函数重载(原理剖析)
      • 1. 重载条件深度解析
      • 2. 底层实现原理
    • 五、缺省参数(陷阱解析)
      • 1. 使用规范示例
      • 2. 声明定义分离规范
      • 3. 常见陷阱
    • 六、引用机制(深入理解)
      • 1. 引用本质
      • 2. 引用使用场景
      • 3. 权限问题详解
    • 七、内联函数(实现原理)
      • 1. 编译器处理逻辑
      • 2. 查看展开效果(GCC)
      • 3. 使用限制
    • 八、符号表与链接错误
      • 1. 多文件编译流程
      • 2. 典型错误分析
    • 九、nullptr(深度解析)
      • 1. NULL的局限性
      • 2. nullptr特性
    • 十、最佳实践指南
      • 1. 命名空间使用建议
      • 2. 函数设计原则
      • 3. 指针/引用选择
    • 补充说明
    • 结语

C++核心特性详解(基础增强版)


一、第一个C++程序:Hello World

完整代码解析

// 包含标准输入输出流头文件
#include <iostream>// 主函数:程序入口
int main() 
{// std::cout 标准输出流对象// << 流插入运算符(将右侧内容输出到左侧流)// std::endl 换行并刷新缓冲区std::cout << "Hello World!" << std::endl;// 返回0表示程序正常退出return 0;
}

新手常见问题

  1. 为什么用std::cout不用printf

    • 类型安全:自动识别变量类型
    • 扩展性好:支持自定义类型输出
    • 代码可读性:<<运算符链式调用更直观
  2. std::endl\n的区别?

    • \n:仅换行
    • std::endl:换行+立即刷新输出缓冲区

二、命名空间(详解版)

1. 为什么需要命名空间?

经典冲突案例

// math.h
int abs(int val) { return val>0?val:-val; }// main.cpp
#include <math.h>
#include <stdlib.h> // 包含标准库的abs()int main() {printf("%d", abs(-5)); // 编译错误:函数重定义return 0;
}

2. 命名空间使用场景

namespace MySpace {int version = 1;void Print() { /*...*/ }class Data { /*...*/ };
}// 使用场景1:明确指定
MySpace::Print();// 使用场景2:局部展开
using MySpace::version;
cout << version;// 使用场景3:全局展开(慎用!)
using namespace MySpace;

3. 嵌套命名空间

namespace Parent {int x = 10;namespace Child {int y = 20;}
}// 访问方式
cout << Parent::Child::y; // 输出20

4. 匿名命名空间

namespace {int count = 0; // 仅当前文件可见
}

三、输入输出系统(深度解析)

1. 输入输出对比

特性C (printf/scanf)C++ (cin/cout)
类型安全需要格式说明符自动类型推导
扩展性不支持自定义类型支持运算符重载扩展
错误处理无编译时检查流状态检测
函数参数可变参数列表运算符链式调用

2. 格式化输出

#include <iomanip> // 需要包含此头文件cout << fixed << setprecision(2) << 3.14159; // 输出3.14
cout << hex << 255;                          // 输出ff

3. 输入注意事项

int age;
double salary;// 正确写法:连续输入
cin >> age >> salary;// 错误处理示例
if (!(cin >> age)) {cout << "输入错误!";cin.clear(); // 清除错误状态cin.ignore(1024, '\n'); // 清空缓冲区
}

四、函数重载(原理剖析)

1. 重载条件深度解析

// 合法重载
void func(int a) {}        // 类型不同
void func(double a) {}void func(int a, int b) {} // 参数个数不同void func(int a, char b) {} // 参数顺序不同
void func(char a, int b) {}// 非法重载
int func(int a) {}         // 仅返回类型不同 ❌
void func(const int a) {}  // const修饰值参数 ❌

2. 底层实现原理

编译器通过**名称修饰(Name Mangling)**生成唯一符号:

  • void func(int)_Z4funci
  • void func(double)_Z4funcPd

查看方法(Linux):

g++ -c test.cpp
nm test.o

五、缺省参数(陷阱解析)

1. 使用规范示例

// 正确:全缺省
void Connect(string ip = "127.0.0.1", int port = 3306) {}// 正确:半缺省(必须从右往左)
void Print(int a, int b = 10, int c = 20) {}// 错误示例
void Error1(int a = 10, int b) {} // 非连续缺省 ❌
void Error2(int a, int b = 10, int c) {} // 中间参数缺省 ❌

2. 声明定义分离规范

// test.h
void Init(int timeout = 1000); // 声明处给缺省值// test.cpp
void Init(int timeout) { /*...*/ } // 定义处不能重复给

3. 常见陷阱

void func(int a, int b = 10) {}
func(,20); // 错误!必须从左向右传参 ❌

六、引用机制(深入理解)

1. 引用本质

int a = 10;
int& ra = a; // 底层实现等效于:
int* const ra = &a;  // 常指针(指向不可变)
*ra = 20;            // 解引用操作

2. 引用使用场景

场景1:函数参数传递

void Swap(int& x, int& y) {int tmp = x;x = y;y = tmp;
}

场景2:函数返回值

int& GetElement(int* arr, int index) {return arr[index];
}

3. 权限问题详解

// 示例1:权限放大
const int a = 10;
int& ra = a;  // 错误!ra可能修改a ❌// 示例2:权限缩小
int b = 20;
const int& rb = b; // 合法 ✅// 示例3:临时对象
int c = 10;
double& rd = c;     // 错误!类型转换产生临时对象 ❌
const double& rd = c; // 正确 ✅

七、内联函数(实现原理)

1. 编译器处理逻辑

inline int Add(int x, int y) {return x + y;
}int main() {int ret = Add(1,2);// 可能被展开为:// int ret = 1 + 2;return 0;
}

2. 查看展开效果(GCC)

g++ -S test.cpp -o test.s

汇编文件内容:

main:movl    $3, -4(%rbp)  // 直接计算结果

3. 使用限制

情况是否支持内联
递归函数
函数体超过10行由编译器决定
虚函数

八、符号表与链接错误

1. 多文件编译流程

.cpp文件 → 编译器 → 目标文件(.o) → 链接器 → 可执行文件(符号表)          (符号解析)

2. 典型错误分析

错误现象:

重复定义`void Print()`

错误原因:

// utils.h
void Print() { /*...*/ } // 被多个cpp文件包含导致多份定义

解决方案:

// utils.h
inline void Print() { /*...*/ }  // 方案1:使用inline// 或
// utils.h
void Print(); // 声明// utils.cpp
void Print() { /*...*/ } // 定义

九、nullptr(深度解析)

1. NULL的局限性

void func(int) {}
void func(int*) {}func(NULL);     // 调用func(int) ❌
func(nullptr);  // 正确调用func(int*) ✅

2. nullptr特性

// 类型检测
cout << typeid(nullptr).name();  // 输出Dn (表示decltype(nullptr))
cout << typeid(NULL).name();     // 输出l (表示long)// 安全转换
int* p1 = nullptr;     // ✅
int* p2 = NULL;        // ✅(C++11前可能警告)
int num = nullptr;     // ❌ 类型不匹配

十、最佳实践指南

1. 命名空间使用建议

  • 项目开发:始终使用命名空间::成员形式
  • 小型测试:可using namespace 命名空间
  • 禁止:在头文件中使用全局using指令

2. 函数设计原则

  • 优先使用引用传参(避免拷贝)
  • 参数超过3个考虑结构体封装
  • 超过50行代码的函数避免使用inline

3. 指针/引用选择

场景推荐使用
需要指向不同对象指针
函数参数传递const引用
返回值需要空值指针
实现多态指针/引用

补充说明

各种报错分析
1.全局函数(声明和定义在一块)被多个.c/.cpp文件展开,报错类型重定义函数,因为这样会导致函数多个进入符号表(粗暴认为符号表内存有的是函数名及其函数地址)内导致重定义
2.解决方法:1.定义和声明分离,由于分.h文件和.c/.cpp文件此时不会进入符号表,之后进行链接操作根据函数名及其地址找到.c/.cpp文件中的定义链接一块即可 2.将函数处理为static放入代码段(常量区),这样就不会进入符号表就算多个.h文件包含也不会因为在符号表内重定义
2.内联函数定义和声明分离和未分离相关讨论
分离:这时候由于内联函数也不会进入符号表因为内联函数使用时是要展开的,这样就没必要进入符号表存入函数名和地址了,但是此时.c/,cpp文件调用这个函数链接时内联展开只有函数声明没有定义这时候导致链接错误
未分离:这样不会出现以上描述情况因为声明和定义未分离可以正常链接

结语

通过这份增强版教程,我们系统性地梳理了C++核心特性,从最基础的Hello World程序到复杂的引用机制,每个知识点都配有详细的代码示例和原理剖析。建议学习时:

  1. 按照章节顺序逐步实践
  2. 重点理解各特性的设计初衷
  3. 通过修改示例代码观察不同表现
  4. 遇到问题优先查看编译器错误提示

C++的学习曲线虽然陡峭,但掌握这些基础后,后续面向对象、模板等高级特性将会更加得心应手。保持编码实践,持续积累经验!
在这里插入图片描述

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

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

相关文章

探秘基带算法:从原理到5G时代的通信变革【三】Turbo 编解码

文章目录 2.2 Turbo 编解码2.2.1 基本概念与系统构成2.2.2 编码过程分步解析交织器递归系统卷积编码器复接器总结 2.2.3 译码算法分类与原理Turbo码的强大主要来源于其解码器理论基础解码过程详解交织与解交织译码算法总结 2.2.4 Turbo码的应用场景无线通信卫星通信深空通信 2.…

一键无损放大视频,让老旧画面重焕新生!

打工人们你们好&#xff01;这里是摸鱼 特供版~ 嘿&#xff0c;朋友们&#xff01;在数字时代&#xff0c;视频已经成为我们生活中不可或缺的一部分。无论是珍贵的家庭录像&#xff0c;还是老旧的影视素材&#xff0c;我们都希望能以高清画质重温那些美好瞬间。但很多时候&…

build gcc

1&#xff0c;下载源码 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpfr-4.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.2.1.tar.gz git clone --mirror https://github…

《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》

导语​ "你是否想过用Python开发一款可玩性高的双人合作游戏&#xff1f;本文将分享如何从零开始实现一款类《吸血鬼幸存者》的生存射击游戏&#xff01;包含完整源码解析、角色系统设计、敌人AI逻辑等核心技术点&#xff0c;文末提供完整代码包下载&#xff01;" 哈…

AutoGen学习笔记系列(一)Tutorial - Model

这个系列文章记录了学习微软 AutoGen 的过程&#xff0c;与 smolagents 学习笔记系列一样&#xff0c;仍然以官方教程自己的理解为主线&#xff0c;中间可能穿插几个番外支线的形式写博客。 【注意】&#xff1a;在阅读这篇文章之前需要确保已经按照其 Installation 小节完成必…

探秘基带算法:从原理到5G时代的通信变革【八】QAM 调制 / 解调

文章目录 2.7 QAM 调制 / 解调2.7.1 概述2.7.2 星座图星座图的结构与性能发射端的信息编码与接收端的解码差分编码的分类与实现差分编码的模4格雷加法器公式16QAM星座图与映射关系 2.7.3 信号表达式正交振幅调制的基本原理与系统分析相位误差对QAM性能的影响多电平正交振幅调制…

本地YARN集群部署

请先完成HDFS的前置部署&#xff0c;部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…

vivado 充分利用 IP 核

充分利用 IP 核 使用预先验证的 IP 核能够大幅减少设计和验证工作量&#xff0c;从而加速产品上市进程。如需了解更多有利用 IP 的信息&#xff0c;请参 阅以下资源&#xff1a; • 《 Vivado Design Suite 用户指南&#xff1a;采用 IP 进行设计》 (UG896) [ 参照 1…

Python-07PDF转Word

2025-03-04-PDF转Word DeepSeek等大模型从来都不是简单的写一个静态博客这么肤浅&#xff08;太多博主都只讲这个内容了&#xff09;借助全网大神的奇思妙想&#xff0c;拓展我狭隘的思维边界。 文章目录 2025-03-04-PDF转Word [toc]1-参考网址2-学习要点3-核心逻辑4-核心代码 …

android11使用gpio口控制led状态灯

目录 一、简介 二、解决方法 A、底层驱动 B、上层调用 C、验证 一、简介 1、需求&#xff1a;这里是用2个gpio口来控制LED灯&#xff0c;开机时默认亮蓝灯&#xff0c;按开机键&#xff0c;休眠亮红灯&#xff0c;唤醒亮蓝灯。 原理图&#xff1a; 这里由于主板上电阻R63…

el-input 设置类型为number时,输入中文后光标会上移,并且会出现上下箭头

光标上移 设置 el-input 的 typenumber后&#xff0c;只能输入数字&#xff0c;输入中文后会自动清空&#xff0c;但是会出现一个问题&#xff1a;【光标会上移&#xff0c;如下图】 解决方法&#xff1a;修改样式 注意&#xff1a;需要使用样式穿透 :deep( ) /*解决el-in…

el-table一格两行;概率;find

样式&#xff1a; 根据概率表头关键代码&#xff1a;rateRanges&#xff1b; scope.row.targetHitTable.find((target:any) > target.targetHitRate > range.min && target.targetHitRate < range.max)!.targetHitNum &#xff08;1&#xff09;!.是TypeScri…

CSS定位详解上

1. 相对定位 1.1 如何设置相对定位&#xff1f; 给元素设置 position:relative 即可实现相对定位。 可以使用 left 、 right 、 top 、 bottom 四个属性调整位置。 1.2 相对定位的参考点在哪里&#xff1f; 相对自己原来的位置 1.3 相对定位的特点&#xff1…

二、Java-封装playwright UI自动化(根据官网执行步骤,首先封装BrowserFactory枚举类及BrowserManager)

前言 查看playwright官网&#xff0c;api文档了解到&#xff0c;playwright的基本步骤&#xff1a; 1、实例化一个playwright 2、启动一个浏览器类型 3、打开一个页面 所以&#xff0c;在封装时需要有一个浏览器工厂类&#xff0c;定义不同的浏览器类型&#xff0c;在配置文…

【问题解决】Jenkins使用File的exists()方法判断文件存在,一直提示不存在的问题

小剧场 最近为了给项目组提供一个能给Java程序替换前端、后端的增量的流水线&#xff0c;继续写上了声明式流水线。 替换增量是根据JSON配置文件去增量目录里去取再替换到对应位置的&#xff0c;替换前需要判断增量文件是否存在。 判断文件是否存在&#xff1f;作为一个老Ja…

神策数据严正声明

近日&#xff0c;我们发现有不法分子冒充神策网络科技&#xff08;北京&#xff09;有限公司&#xff08;以下简称”神策数据”&#xff09;的名义&#xff0c;发布虚假的招聘广告、面试邀请&#xff0c;企图误导求职者并进行不法行为。对此&#xff0c;我司发布严正声明&#…

ICLR 2025|香港浸会大学可信机器学习和推理课题组专场

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; AITIME 01 ICLR 2025预讲会团队专场 AITIME 02 专场信息 01 Noisy Test-Time Adaptation in Vision-Language Models 讲者&#xff1a;曹晨涛&#xff0c;HKBU TMLR Group一年级博士生&#xff0c;目前关注基础…

MySQL增量更新数据:高效同步策略与PanguSync实战指南

Mysql增量更新数据软件下载https://pan.baidu.com/s/1WesHaKGO7uQMhPNE-BTDmg?pwdabcd#list/path%2F 在数据驱动的商业环境中&#xff0c;实时数据同步已成为企业数字化转型的关键。本文将深入探讨MySQL增量更新的核心技术&#xff0c;并详细解析如何通过PanguSync工具实现高…

无人机灯光原理与应用解析!

工作原理 LED光源&#xff1a;LED因其高效、长寿命、高亮度和轻便等优点&#xff0c;成为无人机灯光的主要光源。 电路控制&#xff1a;通过微控制器或飞行控制器调节电流&#xff0c;控制灯光的开关、亮度和颜色。 信号传输&#xff1a;灯光控制信号通过无线或有线方式从遥…

51c自动驾驶~合集52

我自己的原文哦~ https://blog.51cto.com/whaosoft/13383340 #世界模型如何推演未来的千万种可能 驾驶世界模型&#xff08;DWM&#xff09;&#xff0c;专注于预测驾驶过程中的场景演变&#xff0c;已经成为追求自动驾驶的一种有前景的范式。这些方法使自动驾驶系统能够更…