「C++系列」C++ 变量类型
雪梅零落 2024-07-12 09:35:02 阅读 69
文章目录
一、C++ 变量类型1. 基本数据类型2. 复合数据类型3. 类型修饰符
二、C++ 变量定义案例 1: 基本类型变量的定义和初始化案例 2: 数组的定义和使用案例 3: 结构体(Struct)的定义和使用案例 4: 指针的定义和使用案例 5: 类的定义和使用(面向对象)
三、C++ 变量声明变量声明与初始化案例 1: 局部变量和全局变量的声明与定义案例 2: 使用`extern`关键字声明变量案例 3: 使用`auto`和`const`
四、C++ 左值和右值左值(Lvalue)右值(Rvalue)C++11及之后的变化案例 1: 基本的左值和右值案例 2: 使用移动构造函数和移动赋值操作符
五、相关链接
一、C++ 变量类型
C++ 是一种静态类型、编译式、通用、面向对象的编程语言。在 C++ 中,变量是存储信息的容器,并且每个变量都有特定的类型,这个类型决定了变量可以存储什么类型的数据、需要多少存储空间以及可以进行的操作。C++ 提供了多种基本数据类型和复合数据类型来支持不同的编程需求。
1. 基本数据类型
整型(Integer Types)
<code>int:标准的整数类型,用于存储整数值。short
:短整型,用于存储较小的整数值。long
:长整型,用于存储较大的整数值。long long
:更长的整型,用于存储非常大的整数值。unsigned
:与上述类型结合使用,表示无符号类型,即只能存储非负值。
浮点型(Floating-Point Types)
float
:单精度浮点型,用于存储有小数部分的数值。double
:双精度浮点型,用于存储更大范围或更高精度的浮点数。long double
:扩展精度浮点型,提供比 double
更高的精度。
字符型(Character Types)
char
:用于存储单个字符(如字母或标点符号)。
布尔型(Boolean Type)
bool
:表示真(true)或假(false)的布尔值。
枚举类型(Enumeration Types)
enum
:用户定义的类型,包含一组命名的整型常量。
宽字符类型(Wide Character Types)
wchar_t
:用于存储宽字符(如 Unicode 字符)。
2. 复合数据类型
数组(Arrays)
允许存储相同类型数据的固定大小的集合。
结构体(Structures)
允许将不同类型的数据项组合成一个单一的类型。
联合体(Unions)
允许在相同的内存位置存储不同的数据类型,但一次只能使用其中一个。
类(Classes)
C++ 的核心特性之一,支持面向对象编程,包括封装、继承和多态。
指针(Pointers)
存储变量的内存地址,而不是变量的值。
引用(References)
类似于指针,但提供了更高级别的抽象,并且是安全的(不能为空)。
字符串(Strings)
在 C++ 中,字符串可以通过字符数组、std::string
类(C++ 标准库中的一部分)等方式表示。
3. 类型修饰符
signed
和 unsigned
:用于指明整型变量是否有符号。const
:表示变量是常量,其值在初始化后不能被修改。volatile
:告诉编译器该变量的值可能会在程序的控制之外被改变。
二、C++ 变量定义
在C++中,变量定义涉及到指定变量的类型以及变量的名称,并可能包括初始化(即给变量赋一个初始值)。下面将展示几个详细的C++变量定义及使用的案例代码。
案例 1: 基本类型变量的定义和初始化
#include <iostream>
using namespace std;
int main() {
// 定义并初始化整型变量
int age = 30;
// 定义并初始化浮点型变量
float height = 5.9;
// 定义并初始化字符型变量
char gender = 'M';
// 定义布尔型变量并初始化
bool isStudent = true;
// 输出变量值
cout << "Age: " << age << endl;
cout << "Height: " << height << endl;
cout << "Gender: " << gender << endl;
cout << "Is Student: " << (isStudent ? "Yes" : "No") << endl;
return 0;
}
案例 2: 数组的定义和使用
#include <iostream>
using namespace std;
int main() {
// 定义并初始化整型数组
int numbers[] = { 1, 2, 3, 4, 5};
// 遍历数组并打印每个元素
for(int i = 0; i < 5; i++) {
cout << "numbers[" << i << "]: " << numbers[i] << endl;
}
return 0;
}
案例 3: 结构体(Struct)的定义和使用
#include <iostream>
using namespace std;
// 定义结构体
struct Person {
string name;
int age;
float height;
};
int main() {
// 定义并初始化结构体变量
Person person1 = { "John Doe", 30, 6.0};
// 访问结构体成员并打印
cout << "Name: " << person1.name << endl;
cout << "Age: " << person1.age << endl;
cout << "Height: " << person1.height << endl;
return 0;
}
案例 4: 指针的定义和使用
#include <iostream>
using namespace std;
int main() {
// 定义整型变量
int value = 10;
// 定义指向整型的指针变量,并初始化为指向value
int* ptr = &value;
// 通过指针访问变量的值
cout << "Value through pointer: " << *ptr << endl;
// 修改指针指向的值
*ptr = 20;
// 再次通过指针访问变量的值,查看是否已修改
cout << "Modified Value through pointer: " << *ptr << endl;
return 0;
}
案例 5: 类的定义和使用(面向对象)
#include <iostream>
using namespace std;
// 定义类
class Rectangle {
public:
int width, height;
// 构造函数
Rectangle(int w, int h) : width(w), height(h) { }
// 计算面积的方法
int area() {
return width * height;
}
};
int main() {
// 创建Rectangle类的对象
Rectangle rect(5, 7);
// 调用对象的方法并打印结果
cout << "Area of rectangle: " << rect.area() << endl;
return 0;
}
三、C++ 变量声明
在C++中,变量声明(Declaration)和定义(Definition)有时可以互换使用,但在严格意义上它们是有区别的。声明是告诉编译器变量的类型和名称,而定义(也称为初始化)则是为变量分配内存空间并可能赋予一个初始值。然而,在大多数情况下,当你声明一个变量时也会同时定义它(即给出初始值),或者在之后的某个点进行定义。
变量声明与初始化
// 声明一个整型变量,但不在此初始化(即仅声明)
extern int a; // 这通常用于在多个文件中共享变量,但这里只是作为声明的示例
// 声明并初始化一个整型变量
int b = 10; // 这既是声明也是定义
// 声明一个整型变量,稍后在函数内部初始化
int c;
// ...
c = 20; // 现在c被定义了(如果之前没有在其他地方定义)
// 使用auto关键字自动推导类型(C++11及以后)
auto d = 3.14; // d的类型是double,因为3.14是double字面量
// 声明并初始化一个常量(使用const)
const int e = 5; // e是一个常量,其值在编译时确定,且之后不能更改
// 静态局部变量声明(在函数内部)
void func() {
static int f = 0; // f在函数第一次调用时初始化,之后调用时保持其值
f++;
cout << "f: " << f << endl;
}
案例 1: 局部变量和全局变量的声明与定义
#include <iostream>
using namespace std;
// 全局变量声明(通常也是定义)
int globalVar = 100;
void func() {
// 局部变量声明并初始化
int localVar = 20;
cout << "Local variable: " << localVar << endl;
// 访问全局变量
cout << "Global variable: " << globalVar << endl;
}
int main() {
func(); // 调用函数,展示局部变量和全局变量的使用
// 尝试在main中访问localVar会导致编译错误,因为它是func的局部变量
return 0;
}
案例 2: 使用extern
关键字声明变量
当你想在多个源文件中共享变量时,可以使用extern
关键字在一个或多个源文件中声明变量,但在一个源文件中定义它。
#include <iostream>
using namespace std;
// 定义全局变量
int sharedVar = 5;
void printSharedVar() {
cout << "sharedVar in file1.cpp: " << sharedVar << endl;
}
// ...
#include <iostream>
using namespace std;
// 声明全局变量(不初始化)
extern int sharedVar;
void modifySharedVar() {
sharedVar = 10; // 修改在file1.cpp中定义的全局变量
}
// ...
注意:在实际项目中,你还需要确保这些文件被正确地编译和链接,以便extern
声明能够找到变量的定义。
案例 3: 使用auto
和const
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 使用auto自动推导类型
auto x = 10; // x的类型是int
auto y = 3.14; // y的类型是double
// 使用const声明常量
const int maxSize = 100; // maxSize是一个常量,其值在编译时确定
// 使用auto和const一起
const auto z = 20.5; // z的类型是const double
cout << "x: " << x << endl;
cout << "y: " << y << endl;
cout << "maxSize: " << maxSize << endl;
cout << "z: " << z << endl; // 注意:不能直接修改z的值,因为它是const
return 0;
}
四、C++ 左值和右值
在C++中,左值(lvalue)和右值(rvalue)是表达式的一个关键属性,它们与表达式的身份(location)和值(value)有关。左值通常指的是一个具有持久状态的对象,其地址可取,可以被赋值。而右值则是一个临时值,没有持久的存储位置,通常用于表达式的求值过程中,且不能作为左值被赋值。
左值(Lvalue)
有持久的身份(即存储位置)。可以出现在赋值语句的左侧。可以取地址(&
操作符)。
右值(Rvalue)
通常是临时的,没有持久的存储位置。不能出现在赋值语句的左侧(C++11之前)。不能直接取地址(尽管C++11引入了右值引用,允许通过std::move
等方式“模拟”取地址)。
C++11及之后的变化
C++11引入了右值引用(通过&&
表示)和移动语义,使得右值可以被更加高效地处理和利用。此外,还引入了std::move
函数,用于将左值“转换为”右值引用,以便可以使用移动构造函数或移动赋值操作符。
案例 1: 基本的左值和右值
#include <iostream>
#include <string>
int main() {
int a = 5; // a是左值
int b = a; // 合法,因为a是左值
int c = 10 + 20; // c是左值,但10 + 20这个表达式的结果是右值
// int d = 10 + 20; // 这条语句在语法上也是合法的,但10+20的结果(右值)不会“存储”在d中,而是被计算后赋值给d
// 尝试对右值进行取地址操作(编译错误)
// &(10 + 20); // 非法,因为右值没有地址
std::string s1 = "Hello"; // s1是左值
std::string s2 = std::move(s1); // s1在这里被“转换”为右值引用,以便s2可以“窃取”s1的资源
// 注意:此时s1的状态是未定义的,因为s2可能已经“接管”了s1的资源
return 0;
}
案例 2: 使用移动构造函数和移动赋值操作符
为了展示移动语义,我们可以定义一个简单的类,该类包含动态分配的内存,并实现移动构造函数和移动赋值操作符。
#include <iostream>
#include <cstring>
#include <algorithm>
class MyString {
public:
char* data;
size_t len;
// 构造函数
MyString(const char* str) : len(std::strlen(str)) {
data = new char[len + 1];
std::strcpy(data, str);
std::cout << "Constructor called" << std::endl;
}
// 移动构造函数
MyString(MyString&& other) noexcept : data(other.data), len(other.len) {
other.data = nullptr; // 防止析构时释放已移动的资源
other.len = 0;
std::cout << "Move constructor called" << std::endl;
}
// 移动赋值操作符
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data; // 释放当前对象的资源
data = other.data;
len = other.len;
other.data = nullptr; // 防止析构时释放已移动的资源
other.len = 0;
}
std::cout << "Move assignment operator called" << std::endl;
return *this;
}
// 析构函数
~MyString() {
delete[] data;
std::cout << "Destructor called" << std::endl;
}
// 为了简单起见,省略了拷贝构造函数和拷贝赋值操作符
};
int main() {
MyString s1("Hello");
MyString s2 = std::move(s1); // 调用移动构造函数
MyString s3("World");
s3 = std::move(s2); // 调用移动赋值操作符
// 此时s1和s2的资源已被s3接管,
}
五、相关链接
Visual Studio Code下载地址Sublime Text下载地址「C++系列」C++简介、应用领域「C++系列」C++ 基本语法「C++系列」C++ 数据类型
上一篇: [python pip] A new release of pip is available: 23.2.1 -> 24.0
下一篇: Windows 下基于 Visual Studio Code 使用 CMake + MinGW 配置 C++ 开发环境
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。