系列文章
C++编程之引用的详细总结
1、C++命名空间
- 解决命名冲突,保证数据一致性
- 命名空间下可以放变量、函数、结构体、类等
- 命名空间必须声明在全局的作用域下
- 命名空间可以嵌套命名空间,示例如下:
namespace Hero
{
namespace LiBai
{...}
namespace HuangZhong
{...}
}
- 命名空间是开放的,随时可以给其中添加新成员
namespace B
{
int m_A = 100;
}
...
namespace B
{
int m_B = 200;
}
void test()
{
cout<<"B下的m_A="<<B::m_A<<endl;
cout<<"B下的m_B="<<B::m_B<<endl;
}
//两处会合并在一起
- 命名空间是可以匿名的
namespace
{
int m_A = 200;
int m_C = 300;
//相当于在变量前面加了关键字static,类似于全局变量
//static int m_A = 200;
//static int m_C = 300;
}
void test()
{
cout<<m_A<<endl;
cout<<::m_C<<endl; //::前面如果没有任何作用域,代表了使用全局作用域
}
- 命名空间是可以起别名的
namespace HeroNameVeryLongLong
{
string m_name = "赵云";
}
void test()
{
namespace heroName = HeroNameVeryLongLong;
cout<<heroName::m_name<<endl;
cout<<HeroNameVeryLongLong::m_name<<endl;
}
2、C++对C语言的增强
- 全局变量检测增强
#include<stdio.h>
#include<stdlib.h>
int a;
int a = 10;
int main()
{
printf("%d \r\n", a);
system("pause");
return 0;
}
// 上述两行变量a的代码,在C语言中是可以同时存在的。但在C++中不可以同时存在。
- 函数检测增强【以下代码在C中可以正常运行】
#include<stdio.h>
#include<stdlib.h>
// 1、声明函数返回值类型
void GetNum1()
{
return 10;
}
// 2、函数返回值增强,C中函数可以没有返回值,不报错,只有一个警告
int GetAge()
{
int a = 20;
printf("GetAge ..\r\n");
}
// 3、函数声明的返回值增强,在C中函数可以没有返回值
GetNum()
{
return 10;
}
// 4、函数检测增强,C中形参可以没有类型
int GetS(w, h)
{
return w*h;
}
void test1()
{
///5、调用时,C对参数个数的检查也不严格,可以多传入参数。
GetS(10, 23, 45);
}
int main()
{
int a = GetAge();
system("pause");
return 0;
}
- 类型转换增强
#include<stdio.h>
#include<stdlib.h>
// 类型转换增强,在C中可以隐式将void*转换为任意类型的指针,但是C++必须要显式转换,因此以下代码在C++中无法运行。
void test03()
{
char* p = malloc(sizeof(char)* 10);
}
int main()
{
test03();
}
- struct 的增强,C语言中struct中不可以放函数,只能有字段。但是C++中却可以存在函数。
struct Person
{
int age;
};
void test04()
{
// 在C语言中,使用struct时,必须在声明的时候加struct。如果不加,可以使用typedef声明结构体。
// 在C++中,声明的时候可以不加struct ,如 Person p2;
struct Person p1;
p1.age = 1;
}
- bool类型的增强,在C语言中是没有bool类型的。C++中bool类型表示真假,sizeof(bool)=1
- 三目运算符的增强
void test05()
{
int a = 10;
int b = 20;
printf("%d", a > b ? a : b);
// 以下这行代码在C语言中无法通过
//a > b ? a : b = 100; 在C语言中,三目运算符返回的是值。相当于20=100;在C++中,三目运算符返回的是变量,即b=100;
// 当然在C语言下可以使用这种引用的方式让三目运算符返回引用。
*(a > b ? &a : &b) = 100;
- const增强
//1、C语言中,全局变量受到常量区的保护,即使语法通过,运行也会报错。如下代码。
const int m_A = 300;
void test06()
{
//m_A = 400; // 不允许直接修改
int* p = &m_A; // 使用引用修改。语法通过
(*p) = 400;
}
// 2、C语言中,局部常量可以通过引用的方式修改值。局部常量被称为伪常量。
void test07()
{
const int m_B = 200;
m_B=500; // 不允许
int* p = &m_B; // 允许
*p = 300;
//int arr[m_intB]; 伪常量在C语言中是不能初始化数组的。
}
// 1、C++中,全局变量与C语言一样,也是无法修改值。引用或者直接修改都是不行的。
// 2、C++中,局部变量也无法修改,原因是局部常量存储在符号表中,键值对存储,只读类型
void test08()
{
const int m_B = 200;
int* p = (int*)&m_B; // 创建临时变量指向p,本体是不变的。
*p = 300;
int arr[m_B]; //可以初始化数组。
}
//const在C语言中默认是外部链接属性
//const在C++语言中默认是内部链接属性
// 在外部文件textern_const.c中定义如下代码
const int m_DDD = 100; // 默认在最前面加了extern
// 在test.c中声明后直接使用。
void test08()
{
extern const int m_DDD;
printf("%d \r\n", m_DDD);
}
// C语言中是可以正常使用的,验证了const的外部链接属性。在C++中这样是无法运行的。
//-------------------------------------------------------------
// C++中,外部定义需要如下.
extern const int m_A = 200; // 这样在其他文件中才会被访问到,extern提高作用域。
3、const分配内存
- 对const修饰的变量取地址的时候,会分配临时内存
- const前加了extern后,也会分配内存。
- 使用变量初始化const修饰的变量。
#include<iostream>
using namespace std;
void test01()
{
int a = 10;
//const int m_B = 30; // 直接初始化是常量,无法修改值,存储符号表中。
const int m_A = a; //用变量初始化的常量,会分配内存,可以间接修改值。
int* p = (int*)&m_A;
*p = 40;
cout << m_A << endl;
cout << a << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
- 对于自定义的数据类型,也会分配内存。
#include<iostream>
using namespace std;
#include<string>
struct Person
{
string name;
int age;
};
void test02()
{
const Person p;
// 不能直接修改
/*p.name = "123";
p.age = 20;*/
Person* p1 = (Person*)&p;
p1->name = "12345";
p1->age = 23;
cout << p.age << endl;
cout << p.name << endl;
}
int main()
{
test02();
return 0;
}
- const与#define的区别
1、const有类型,可以进行编译类型安全检查,#define无类型。
2、const有作用域,而#define不重视作用域,默认定义处到文件结尾,如果定义在指定作用域下有效的常量,那么#define不能用。
注:以上是本次疫情期间学习某大神精心录制的视频以及阅读《C++ Primer Plus (第6版)》后总结的学习笔记,后续会继续更新学习笔记,记录学习成长点滴。
原文来自我的有道云笔记