【C++入门核心语法精讲:从新手村到实战高手的必经之路】

你好,这里是新人 Sunfor

这篇是我最近对于C++入门语法的学习心得和错题整理
有任何错误欢迎指正,欢迎交流!
会持续更新,希望对你有所帮助,我们一起学习,一起进步

📌前言

“真正优秀的C++程序员,往往能把基础语法玩出花来”
本文将带大家深入C++核心语法细节,这些知识不仅是面试的高频考点,更是项目实践中提升代码质量的利器

一、命名空间(namespace) ----你的代码领域宣言

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

  • “命名空间是代码世界的国界线,避免符号战争的终极方案”
    解决全局作用域下的标识符污染问题
    经常运用于解决 多人协作开发 时的符号冲突

2.命名空间的定义

  • 通过 namespace 关键字声明独立作用域,不同的域可以定义同名变量

C++中的域有函数局部域,全局域,命名空间域,类域
域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所以有了
域的隔离,名字冲突就解决了
注意: 局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期
命名空间域和类域不会影响变量生命周期

  • namespace只能定义在全局,当然也可以嵌套定义
  • 项目工程中多文件定义的同名namespace会认为是一个namespace,不会冲突
  • C++标准库都放在一个std(standard)的命名空间中

3.使用示范

//your first C++ program
//c语言版本
#include<stdio.h>

int main()
{
	printf("Hello World!\n");
	return 0;
}
//c++版本
#include<iostream>
using namespace std;

int main()
{
	cout << "Hello World!\n" << endl;

	return 0;
}

//命名空间的嵌套
namespace yw
{
	namespace sun
	{
		int rand = 1;

		int Add(int left, int right)
		{
			return left + right;
		}
	}

	namespace flower
	{
		int rand = 2;

		int Add(int left, int right)
		{
			return (left + right) * 10;
		}
	}
}

int main()
{
	printf("%d\n", yw::sun::rand);
	printf("%d\n", yw::flower::rand);

	printf("%d\n", yw::sun::Add(1, 2));
	printf("%d\n", yw::flower::Add(1, 2));

	return 0;
}
//全局域vs局部域
int x = 0;
namespace yw
{
	int x = 1;
}

void func()
{
	int x = 2;//局部域的只能在局部访问
}

int main()
{
	int x = 3;

	printf("%d\n", x);//访问自身的 默认从局部到全局 不会去命名空间找
	printf("%d\n", yw::x);//访问命名空间的  主要为了与全局隔离
	printf("%d\n",::x);//访问全局的
	
}

💡 行业规范

大型项目必须使用命名空间,禁止在头文件中使用 using namespace

二、缺省参数 ----智能的函数参数设计

1.为什么要有缺省参数?

“让函数接口具备弹性,向后兼容的巧妙设计”
简化函数调用复杂度,支持接口升级时不破坏旧代码

2.缺省参数的定义

缺省参数是声明和定义函数时为函数的参数指定一个缺省值,在调用该函数时,如果没有指定实参则采用该形式的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值,半缺省参数必须从右往左连续缺省,不能间隔跳跃给缺省值

注意:C++规定必须从左到右依次给实参,不能跳跃给实参
函数声明和定义分离时,缺省参数不能在函数声明和定义同时出现,规定必须函数声明给缺省值

3.缺省参数的使用

void Func(int a = 10)
{
	cout << a << endl;
}

int main()
{
	Func();
	Func(1);

	return 0;
}

//全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
//半缺省(必须从右往左给值)
void Func2(int a, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	Func1();
	Func1(1);
	Func1(1, 2);
	Func1(1, 2, 3);
	//Func1(,2,)不允许越级传,只能从左到右

	Func2(100);//至少给一个参数
	Func2(100, 200);
	Func2(100, 200, 300);
}

//不知道用缺省 知道就显示传递 就与缺省值无关就不会开辟额外的空间
//缺省参数不能在声明和定义处同时出现 在声明地方给 定义不能给

三、函数重载 ----优雅的多面手

1.为什么要有函数重载?

“函数重载是C++给程序员的语义画笔,让相同操作的不同形态拥有统一的名字”
允许同名函数根据参数列表差异执行不同逻辑,提升代码可读性,实现自然语义化编程

2.函数重载的定义

函数名相同,参数列表必须满足以下差异之一
1.参数类型不同
2.参数个数不同
3.参数顺序不同

不构成重载的情况:仅返回值不同‘

3.函数重载的使用

int Add(int left, int right)
{
	cout << "int Add(int left,int right)" << endl;
	return left + right;
}

double Add(double left, double right)
{
	cout << "double Add(double left,double right)" << endl;
	return left + right;
}

void f()
{
	cout << "f()" << endl;
}

void f(int a)
{
	cout << "f(int a)" << endl;
}

void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}

void f(char b, int a)
{
	cout << "f(char b,int a)" << endl;
}
//参数不同可以构成重载 返回值不同不能区分

int main()
{
	Add(1, 2);
	Add(1.1, 2.2);
	f();
	f(10);

	f(19, 'a');
	f('a', 19);

	return 0;
}

四、引用 ----指针的安全马甲

1.为什么要有引用?

“安全的指针替身,函数式编程的基石”
提供变量别名,避免指针的复杂操作,实现高效安全的数据传递

2.引用的定义

引用不是定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和引用的变量共用同一块内存空间
类型& 引用别名 = 引用对象

  • 引用在定义时必须初始化
  • 一个变量可以有多个引用
  • 引用一旦引用一个实体,再不能引用其他实体

3.引用的使用

// 1. 函数参数传递(避免拷贝)
void ProcessBigData(const BigClass& obj);

// 2. 函数返回值(延长生命周期)
const string& GetName() { 
    static string name = "test";
    return name; // 必须返回静态或全局变量
}

// 3. 范围for循环
for (auto& num : nums) {
    num *= 2; // 直接修改容器元素
}

注意

引用和指针在实践中相辅相成,功能具有重叠性,但各有特点,互相不可替代
C++的引用跟其他语言的引用有很大区别,引用定义后不改变指向

4.const引用

可以引用const对象,但必须使用const引用。同时,const引用也能引用普通对象,因为在引用过程中可以缩小对象的访问权限,但无法扩大权限。

举个例子

int main()
{
	const int a = 10;

	//权限不能放大
	//int& ra = a;
	const int& ra = a;

	//权限可以缩小
	int b = 1;
	const int& rb = b;

	return 0;
}

五、inline函数 ----性能优化的秘密武器

1.为什么要有inline函数?

”性能于可维护性的平衡艺术“
消除函数调用开销,替代宏函数的同时保持类型安全
替代C的宏定义

2.inline函数的定义

用inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数就需要建立栈帧,就可以提高效率
inline关键字对编译器而言仅是一种建议,这意味着即使你为函数添加了inline,编译器也可能选择不在调用处展开。由于C++标准并未对此作出明确规定,不同编译器在何种情况下展开inline函数的行为各有差异。一般来说,inline适用于频繁调用且代码较短小的函数,而对于递归函数或代码较为复杂的函数,即使标注了inline,编译器通常也会忽略该建议。
inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地 址,链接时会出现报错。

3.inline函数的使用

//正确的宏的写法
#define ADD(a,b)((a) + (b))
//不能加; 本质是替换 
//要加外面的括号 要考虑符号的优先级
//& | 这种情况也需要考虑运算优先级
//宏函数缺点很多,但是替换机制不用建立栈帧

int main()
{
	int ret = ADD(1, 2);

	cout << ret << endl;

	cout << ADD(1, 2) << endl;

	return 0;
}
inline int Add(int x, int y)
{
	int ret = x + y;
	return x + y;
}

int main()
{
	int x = 1, y = 2;
	int re = Add(x & y, x | y);
	cout << re << endl;

	return 0;
}

六、nullptr ----C++11的类型安全革命

1.为什么要有nullptr?

”类型安全的空指针革命“
解决C语言NULL的二义问题(0 vs (void*)0),明确指针空值语义

2.nullptr的定义

nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换 成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被 隐式地转换为指针类型,⽽不能被转换为整数类型

void func(int) { cout << "int version" << endl; }
void func(int*) { cout << "pointer version" << endl; }

int main() {
    func(NULL);     // 可能调用int版本!
    func(nullptr);  // 明确调用指针版本
}

3.nullpter的使用

#include<iostream> 
using namespace std;

void f(int x) 
{ 
	cout << "f(int x)" << endl; 
}

void f(int* ptr) 
{
	cout << "f(int* ptr)" << endl; 
}
int main() 
{
	f(0);
	// 本想通过f(NULL)调⽤指针版本的f(int*)函数,但是由于NULL被定义成0,调⽤了f(int x),
	// 因此与程序的初衷相悖
	f(NULL); 
	f((int*)NULL);
	// 编译报错:error C2665: “f”: 2 个重载中没有⼀个可以转换所有参数类型
	// f((void*)NULL);
	f(nullptr); 
	return 0; 
}

💡 避坑指南

  • 避免跨作用域的缺省参数
  • 不要返回局部对象的引用
  • inline函数不宜超过10行
  • 优先使用const引用传递大型对象

结语

真正掌握这些语法特性,需要在实际项目中反复锤炼。建议读者将本文代码示例手敲三遍,体会每个语法细节的设计哲学。下期我们将深入探讨C++面向对象编程的精髓,敬请期待!

👉 互动环节:大家在项目中遇到过哪些因基础语法使用不当引发的Bug?欢迎评论区分享讨论!

碎碎念time

消失了快3个月啦,实在对关注我的朋友们感到抱歉
这三个月里确实没有系统性的学习编程知识,也确实发现生活没有编程真的很无趣无味
不知道大家是否也会向我一样间歇性摆烂,在清醒中沉沦呢?
其实我们所有的道理都明白,但是到我们自己需要做的时候就不像脑海中幻想的那么简单
学习的路上更是最明显的体现,我们知道一切收获都需要付出相应的时间与精力
但每当遇到瓶颈和阻拦的时候,就很难坚持下去
多的也不多说,希望大家都能保持初心,久久做功!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值