C++primer 第二章 变量和基本类型

昨天思考了一下,感觉明白了。于是报名了软考,还有挑战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;

}

```

  1. 块作用域(Block Scope):
  • 在函数、语句块或循环中声明的变量具有块作用域,只能在其所在的块或内层块中访问。

  • 示例代码:

cpp 复制代码
     ```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;
     }
     ```
  1. 函数参数作用域(Function Parameter Scope):
  • 函数参数具有函数参数作用域,只能在函数体内部访问。

  • 示例代码:

cpp 复制代码
     ```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;
     }
     ```
  1. 类作用域(Class Scope):
  • 在类定义中声明的成员变量具有类作用域,可以在整个类中访问。

  • 示例代码:

cpp 复制代码
     ```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;
     }
     ```

这些是变量作用域的几个常见示例,每个作用域都有其特定的可见范围和生命周期。正确使用变量的作用域可以提高代码的可读性、避免命名冲突以及有效地管理变量的生命周期。

引用和指针

cpp 复制代码
#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。

  1. 指针和引用的用途不同:
  • 指针通常用于动态内存分配、数组及链表等数据结构的实现,以及函数参数传递。

  • 引用通常用于函数的返回值、函数参数传递和类的成员变量。

  1. 指针和引用的空间占用不同:
  • 指针在32位系统中通常占用4个字节,在64位系统中通常占用8个字节,而且每次访问指针变量时都需要额外的开销。

  • 引用本身不占用额外的内存空间,它只是原变量的另一个名称,所以访问引用的速度通常比访问指针快。

  1. 指针和引用的空值处理不同:
  • 指针可以为空或NULL,需要在使用时进行判断,否则可能会导致程序崩溃。

  • 引用不能为NULL或空,一旦被定义,就必须指向一个已经存在的变量。

const限定符

顶层const:表示指针是一个常量

底层const:表示指针所指的是一个常量

  1. **顶层 const**:

    • 顶层 const 出现在对象的最顶层,表示对象本身是一个常量。这意味着你不能通过这个指针或引用来修改对象的值,但可以改变指针或引用指向其他对象。
    cpp 复制代码
    const int x = 5; // x 是一个顶层 const,不可修改
    int const y = 10; // 与上面相同,x 和 y 是等价的
    
    const int* ptr = &x; // ptr 是一个指向常量整数的指针,不允许通过 ptr 修改 x 的值

    复制

  2. **底层 const**:

    • 底层 const 出现在对象的底层,表示对象本身可修改,但不能通过这个指针或引用来修改对象的值。
    cpp 复制代码
    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 复制代码
```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 的常见用法示例:

cpp 复制代码
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 分别为 intdoubleint*、匿名结构体以及函数指针定义了新的类型名。使用这些新类型名时,就相当于使用原类型。

typedef 在 C++ 中广泛用于提高代码的可读性和可维护性。它特别适用于复杂的类型和函数指针的声明,可以避免编写冗长的类型名,并使代码更加清晰易懂。然而,自 C++11 起,还引入了更加灵活和强大的类型别名机制 using,建议在新的代码中使用 using 来替代 typedef。例如,上述示例可以改写为以下形式:

cpp 复制代码
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 复制代码
 ```cpp
   int x = 5;
   decltype(x) y;  // 推导出 y 的类型为 int
   ```

这里 `decltype(x)` 推导出的类型为 `int`,因为变量 `x` 的初始化表达式是整数值 5。

  1. 推导表达式的类型:通过 `decltype` 可以根据表达式来推导出该表达式的类型。例如:
cpp 复制代码
   ```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 复制代码
```cpp
int x = 5;
decltype(x) y = x;  // 推导出 y 的类型为 int
```

`decltype` 是一个非常有用的类型指示符,可以在编译时获取表达式的类型,并且能够根据变量初始化表达式来推导出变量的类型。它可以用于声明变量、定义函数返回类型等场景,提高代码的可读性和灵活性。

相关推荐
ac-er88881 分钟前
PHP弱类型安全问题
开发语言·安全·php
ac-er88882 分钟前
PHP网络爬虫常见的反爬策略
开发语言·爬虫·php
爱吃喵的鲤鱼12 分钟前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
DARLING Zero two♡38 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
7年老菜鸡39 分钟前
策略模式(C++)三分钟读懂
c++·qt·策略模式
Gu Gu Study40 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
Ni-Guvara1 小时前
函数对象笔记
c++·算法
似霰1 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
芊寻(嵌入式)1 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
獨枭1 小时前
C++ 项目中使用 .dll 和 .def 文件的操作指南
c++