昨天思考了一下,感觉明白了。于是报名了软考,还有挑战z杯,想着四级还要不要报,毕竟我也不是有天赋的人,就只能努力去做个努力的人。加油!!! 不知道未来怎么样,那就走好现在吧!!!
C++中的类型
C++语言中有多种类型,包括基本数据类型、复合数据类型和用户自定义类型。以下是C++的一些常见类型:
1. 基本数据类型(Primitive Data Types):
- 整数类型:int、short、long、long long、unsigned等。
- 浮点数类型:float、double。
- 字符类型:char、wchar_t、char16_t、char32_t。
- 布尔类型:bool。
2. 复合数据类型(Compound Data Types):
- 数组(Array):存储相同类型的多个元素的集合。
- 结构体(Struct):将不同类型的数据聚集到一个对象中。
- 联合体(Union):使用相同的内存位置存储不同类型的数据。
- 枚举(Enum):定义具有离散取值集合的新类型。
3. 指针类型(Pointer Types):
- 指针(Pointer):存储内存地址的变量,用于间接访问和修改数据。
- 空指针(nullptr):表示指针不指向任何有效的内存位置。
- 空类型指针(void*):指向未知类型的指针。
4. 引用类型(Reference Types):
- 引用(Reference):为变量起别名,在声明时使用&操作符。
5. 常量类型(Constant Types):
- const:用于声明常量,值不能被修改。
- constexpr:用于在编译时计算表达式的常量。
6. 自定义类型(User-defined Types):
- 类(Class):封装数据和函数的用户定义类型。
- 枚举类(Enum class):具有强类型和作用域的枚举类型。
- 联合体(Union):使用相同的内存位置存储不同类型的数据。
- 结构体(Struct):将不同类型的数据聚集到一个对象中。
- 类型别名(Typedef):为现有类型创建新的类型名称。
- using 声明(using declaration):引入命名空间中的特定成员。
其中bool类型是一个字节,char类型一个字节,wchar_t为宽字符为16个字节。。。
int整形通常是四个字节,不过在计算中我们通常作为16个字节数。
类型转换:
通常是精度较高的类型向较低类型转换可以,反之则不行。
变量名的作用域
在C++中,变量的作用域决定了变量在程序中的可见性和生命周期。以下是几种常见的变量作用域及其代码案例:
1. 全局作用域(Global Scope):
- 在函数体外部声明的变量具有全局作用域,可以在整个程序中访问。
- 示例代码:
```cpp
#include <iostream>
int globalVariable = 10; // 全局变量
void printGlobalVariable() {
std::cout << "Global variable: " << globalVariable << std::endl;
}
int main() {
printGlobalVariable(); // 输出:Global variable: 10
return 0;
}
```2. 块作用域(Block Scope):
- 在函数、语句块或循环中声明的变量具有块作用域,只能在其所在的块或内层块中访问。
- 示例代码:
```cpp #include <iostream> void printNumber() { int number = 5; // 块作用域变量 std::cout << "Number: " << number << std::endl; } int main() { printNumber(); // 输出:Number: 5 // std::cout << number; // 错误:无法访问printNumber函数中的number变量 return 0; } ```
3. 函数参数作用域(Function Parameter Scope):
- 函数参数具有函数参数作用域,只能在函数体内部访问。
- 示例代码:
```cpp #include <iostream> void printName(std::string name) { std::cout << "Name: " << name << std::endl; } int main() { std::string myName = "Alice"; // 局部变量 printName(myName); // 输出:Name: Alice // std::cout << name; // 错误:无法访问printName函数中的name参数 return 0; } ```
4. 类作用域(Class Scope):
- 在类定义中声明的成员变量具有类作用域,可以在整个类中访问。
- 示例代码:
```cpp #include <iostream> class MyClass { public: int memberVariable = 20; // 类成员变量 void printMemberVariable() { std::cout << "Member variable: " << memberVariable << std::endl; } }; int main() { MyClass obj; obj.printMemberVariable(); // 输出:Member variable: 20 return 0; } ```
这些是变量作用域的几个常见示例,每个作用域都有其特定的可见范围和生命周期。正确使用变量的作用域可以提高代码的可读性、避免命名冲突以及有效地管理变量的生命周期。
引用和指针
#include<iostream>
using namespace std;
int main()
{
int b = 10;
int *a=&b;
int** c = &a;
cout << **c<< endl;
return 0;
}
在代码中*a=&b a的值等于b的地址,与就是 a的值为&b,*a就是指向a的值的地址的值,就是指向&b位置的值。
指针和引用的区别
指针和引用是C++语言中两种不同的机制,它们都可以用于间接操作内存中的值,但是它们之间有以下几个最大的区别:
1. 指针和引用的定义方式不同:
- 指针是一个变量,其存储的值为另一个变量的地址,需要使用*(解引用运算符)来获取所指向的值。指针可以为空或NULL,可以被重新赋值指向不同的内存地址。
- 引用是一个已经存在的变量的别名,一旦被定义,就不能被改变指向其他变量,也不能为空或NULL。2. 指针和引用的用途不同:
- 指针通常用于动态内存分配、数组及链表等数据结构的实现,以及函数参数传递。
- 引用通常用于函数的返回值、函数参数传递和类的成员变量。3. 指针和引用的空间占用不同:
- 指针在32位系统中通常占用4个字节,在64位系统中通常占用8个字节,而且每次访问指针变量时都需要额外的开销。
- 引用本身不占用额外的内存空间,它只是原变量的另一个名称,所以访问引用的速度通常比访问指针快。4. 指针和引用的空值处理不同:
- 指针可以为空或NULL,需要在使用时进行判断,否则可能会导致程序崩溃。
- 引用不能为NULL或空,一旦被定义,就必须指向一个已经存在的变量。
const限定符
顶层const:表示指针是一个常量
底层const:表示指针所指的是一个常量
-
**顶层
const
**:- 顶层
const
出现在对象的最顶层,表示对象本身是一个常量。这意味着你不能通过这个指针或引用来修改对象的值,但可以改变指针或引用指向其他对象。
const int x = 5; // x 是一个顶层 const,不可修改 int const y = 10; // 与上面相同,x 和 y 是等价的 const int* ptr = &x; // ptr 是一个指向常量整数的指针,不允许通过 ptr 修改 x 的值
复制
- 顶层
-
**底层
const
**:- 底层
const
出现在对象的底层,表示对象本身可修改,但不能通过这个指针或引用来修改对象的值。
int a = 5; int const* ptr = &a; // ptr 是一个指向整数常量的指针,a 是可修改的,但不能通过 ptr 修改 a 的值 const int* constPtr = &a; // 同上,ptr 和 constPtr 是等价的
- 底层
const
在函数参数中常用于指明参数是只读的,从而防止函数内部修改参数的值。
void foo(const int x) { // 在函数内部,x 是只读的,不能修改它的值 }
- 底层
总结一下:
- 顶层
const
表示对象本身是常量,不能被修改。 - 底层
const
表示指向的对象是常量,但指针或引用本身可以修改
constexpr常量表达式
`constexpr` 是 C++11 引入的关键字,用于声明常量表达式。常量表达式是在编译时就可以计算出结果的表达式,它具有以下特点:
1. 在编译时求值:常量表达式的值必须在编译时能够确定,不能依赖于运行时的输入或其他动态操作。
2. 编译时优化:编译器可以对常量表达式进行求值,并在编译期间进行优化,减少运行时的开销。
3. 用于常量定义:常量表达式可以用于定义常量变量,并在程序中使用。
使用 `constexpr` 关键字声明常量表达式时,需要满足一定的条件:
1. 表达式必须是编译时可求值的,不能含有任何可能运行时才能确定的值或操作。
2. 表达式中只能使用内置类型、字面值、函数调用(如果函数本身也是 `constexpr` 的),以及支持的运算符。
3. 声明常量表达式的函数本身也要被声明为 `constexpr`。
下面是一个示例代码,演示了如何使用 `constexpr` 声明和使用常量表达式:
```cpp
#include <iostream>
constexpr int square(int x) {
return x * x;
}
int main() {
constexpr int radius = 5;
constexpr int area = square(radius) * 3.14;
std::cout << "半径为 " << radius << " 的圆的面积是 " << area << std::endl;
return 0;
}
```
在上面的代码中,`square` 函数被声明为 `constexpr`,它接受一个整数参数并返回该整数的平方。在 `main` 函数中,使用 `constexpr` 声明了常量 `radius` 和 `area`,并通过调用 `square` 函数计算圆的面积。由于所有的操作都是在编译时确定的,因此 `area` 的计算也可以在编译期间完成。
typedef
类型别名
typedef
是 C++ 中的一个关键字,用于为类型定义一个新的别名或类型名。通过使用 typedef
,可以为已有的类型赋予一个更具描述性的名称,提高代码的可读性和可维护性。
typedef
的语法形式如下:
typedef 原类型 新类型名;
其中,原类型
表示要定义别名的已有类型,新类型名
是所定义的新类型。
下面是一些 typedef
的常见用法示例:
typedef int myInt; // 将 int 类型定义为 myInt
typedef double Distance; // 将 double 类型定义为 Distance
typedef int* IntPtr; // 将 int* 类型定义为 IntPtr
typedef struct {
int x;
int y;
} Point; // 将匿名结构体定义为 Point
typedef void (*FunctionPtr)(int); // 将函数指针定义为 FunctionPtr,指向接受 int 参数且返回值为 void 的函数
在上述示例中,我们使用 typedef
分别为 int
、double
、int*
、匿名结构体以及函数指针定义了新的类型名。使用这些新类型名时,就相当于使用原类型。
typedef
在 C++ 中广泛用于提高代码的可读性和可维护性。它特别适用于复杂的类型和函数指针的声明,可以避免编写冗长的类型名,并使代码更加清晰易懂。然而,自 C++11 起,还引入了更加灵活和强大的类型别名机制 using
,建议在新的代码中使用 using
来替代 typedef
。例如,上述示例可以改写为以下形式:
using myInt = int;
using Distance = double;
using IntPtr = int*;
struct Point {
int x;
int y;
};
using FunctionPtr = void (*)(int);
decltype类型指示符
`decltype` 是 C++11 中引入的一个类型指示符(type specifier)。它用于从表达式中推导出其类型,并在编译时确定该表达式的类型。
`decltype` 的语法形式如下:
decltype(expression)其中,`expression` 是一个有效的 C++ 表达式,可以是任意合法的表达式,包括变量、函数调用、运算符操作等。
`decltype` 主要有两种使用方式:
1. 推导变量的类型:通过 `decltype` 可以根据变量的初始化表达式来推导出变量的类型。例如:
```cpp int x = 5; decltype(x) y; // 推导出 y 的类型为 int ```
这里 `decltype(x)` 推导出的类型为 `int`,因为变量 `x` 的初始化表达式是整数值 5。
2. 推导表达式的类型:通过 `decltype` 可以根据表达式来推导出该表达式的类型。例如:
```cpp int a = 10; double b = 5.5; auto result = a + b; decltype(a + b) sum; // 推导出 sum 的类型为 double ```
这里 `decltype(a + b)` 推导出的类型为 `double`,因为表达式 `a + b` 的结果是一个浮点数。
需要注意的是,`decltype` 不会执行表达式,只负责推导表达式的类型。此外,如果表达式是一个变量名而不是一个初始化表达式,`decltype` 推导的类型将是该变量声明时的类型。例如:
```cpp int x = 5; decltype(x) y = x; // 推导出 y 的类型为 int ```
`decltype` 是一个非常有用的类型指示符,可以在编译时获取表达式的类型,并且能够根据变量初始化表达式来推导出变量的类型。它可以用于声明变量、定义函数返回类型等场景,提高代码的可读性和灵活性。