C++知识点杂记1——typedef、static_cast、const_cast、遍历二维数组、聚合类

本文深入探讨了C++中的类型别名(typedef)、类型转换(static_cast、const_cast)的使用方法及注意事项,解析了二维数组的遍历技巧,并介绍了聚合类的特性与初始化方式。

1.typedef

typedef一般是对某种类型的类型别名(不是变量别名)

typedef double db;

void mixtypename()
{
	db d=1.2;
	cout<<d<<endl;
}

db就是double的别名,一般情况下,使用typedef一般可以认为是类型别名的替换

 

但是也有例外

typedef char * ps;
void mixtypenameexcept()
{
	char a='s';
	char b='a';
	const ps cstr=&a;
	cstr=&b;
}

当编译这段代码时,会报错

这说明cstr是const指针,而不是指向const变量的指针

也就是说

const ps cstr等价于char *const cstr
const ps cstr不等价于const char *cstr

 

2.static_cast

static_cast用来强迫隐式转换。那么经常出现的隐式转换有哪些?1、用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。2、指针或引用之间的转换,比如 void*转为float*,或者将base*转为derived*。3、将非const对象转为const对象。

void mixtypecast()
{
	double d=3.14;
	int i=static_cast<int>(d);
	void *vp=&i;
	int *pi=static_cast<int *>(vp);
	cout<<i<<endl<<*pi<<endl;
}

int i=10;
const double d=static_cast<double>(i);
base *pb=new base();
derive *pd=new derive();
base *pb2=static_cast<base*>(pd);
derive *pd2=static_cast<derive*>(pb);//not safe
base b;
base &rb=b;
derive &rd=static_cast<derive&>(rb);//not safe

上述代码中的L6、9发生了向下转化,是不安全的(因为编译期的类型转换有可能会在运行时出现错误,特别是类对象的指针或引用),所以就有了dynamic_cast,dynamic_cast见https://blog.youkuaiyun.com/Master_Cui/article/details/110520918

 

3.const_cast

const_cast通常被用来将对象的底层const属性。所以,const_cast一般用于const对象引用和const对象的指针,但是不能用于const对象

示例

void mixremoveconst()
{
	const int &a=10;
	int &b=const_cast<int &>(a);

	const int *pa=&a;
	int *p=const_cast<int *>(pa); 

	cout<<p<<endl<<b<<endl;
}

 

示例2

const int cb=20; 
int b=const_cast<int>(cb);

cb中的const是顶层const,所以不能用const_cast来强转,否则会出现如下错误(提示被转换的表达式不是指针也不是引用)

 

 

4.一次循环遍历二维数组

void twodimarray()
{
    int a[3][4]={1,2,3,4,5};
    for (int i=0;i<3*4;++i) {
        cout<<a[i/4][i%3]<<endl;
    }
}

行下表为数组元素索引除列数,列下表为数组元素索引对行求余

 

5.聚合类

聚合类的特点:1.所有成员都是public。2.没有定义任何构造函数,全有编译器自动生成。3.没有基类。4.没有类内初始化

可以使用列表初始化对聚合类进行初始化,成员初始化的顺序必须和成员的定义顺序一致

class agg
{
public:
	int a;
	string str;
};

int main(int argc, char const *argv[])
{
	agg t={10,"qwe"};
	cout<<t.a<<t.str<<endl;
	return 0;
}

上述代码中的10和qwe的位置不能颠倒

 

 

参考:

《C++ Primer》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

<think> 首先,用户的问题是关于C++中的reinterpret_caststatic_cast的含义。他们提供了三个引用,我需要参考这些引用,但也要基于我的知识给出准确解释。引用是: - 引用[1]: reinterpret_cast处理无关类型之间的转换,保持相同的比特位。 - 引用[2]: static_cast尝试转换类型(如float到integer),而reinterpret_cast改变编译器意图将对象视为另一种类型。 - 引用[3]: 讨论了类型转换,包括隐式和显式转换,但没有直接针对这两个cast。 用户的问题很简单:"我想了解reinterpret_caststatic_cast的含义",所以我要解释这两个运算符的含义、区别和用法。 系统级指令要求: - 行内数学表达式用$...$,比如$x^2$。 - 独立公式用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,逐步解决问题。 - 用户可见层:确保回答真实可靠。 结构我的回答: 1. **引言**:简要介绍类型转换在C++中的重要性。 2. **解释static_cast**:含义、用法、示例。 3. **解释reinterpret_cast**:含义、用法、示例。 4. **比较区别**:基于引用[1]和[2],突出关键差异。 5. **安全性考虑**:讨论潜在风险。 6. **生成相关问题**:在末尾添加相关问题。 确保内容真实可靠: - static_cast用于相关类型转换,如数值转换或类层次转换。 - reinterpret_cast用于不相关类型转换,如指针指针或整数到指针,直接重新解释比特位。 - 提供简单代码示例(用中文注释)。 添加引用: - 在相关段落末尾添加[^1]、[^2],基于用户提供的引用。 数学表达式:如果有涉及数学,比如比特操作,使用$...$或$$...$$。但在这个主题中,数学可能不多,重点是概念。 最终,生成相关问题。 回答大纲: 1. 开头:解释C++中类型转换的需要。 2. static_cast部分:定义、例子(如int到float)。 3. reinterpret_cast部分:定义、例子(如指针到整数)。 4. 区别总结。 5. 警告:reinterpret_cast的危险性。 6. 相关问题。 现在,构建具体内容。 </think>### reinterpret_caststatic_cast的含义及区别 在C++中,类型转换是处理不同类型数据交互的核心机制。`static_cast`和`reinterpret_cast`是两种显式转换运算符,用于在不同场景下强制改变变量的类型。它们都属于C++的“新式转型”(new-style casts),旨在替代旧式的C风格强制转换(如`(int)ptr`),以提供更清晰的语义和类型安全[^3]。以下是基于C++标准的详细解释和示例。 #### 1. **static_cast的含义** `static_cast`用于**相关类型之间的转换**,这些类型在逻辑上有关联(如数值类型转换或类继承关系)。编译器会尝试执行类型检查,并在可能时进行隐式转换(如提升精度或降低精度)。如果转换无效,编译器会报错。 - **核心特性**: - 执行编译时的类型检查,确保转换在语义上合理[^2]。 - 支持数值转换(如`float`到`int`)、指针在类层次中的上下转换(如基类指针到派生类指针),以及枚举和整数之间的转换。 - 不改变原始数据的比特位表示;而是基于类型规则重新解释值[^1]。 - **示例**: ```cpp float f = 3.14f; int i = static_cast<int>(f); // 转换float到int:值从3.14变为3(精度丢失,但类型安全) class Base {}; class Derived : public Base {}; Base* basePtr = new Derived(); Derived* derivedPtr = static_cast<Derived*>(basePtr); // 向下转型:安全,因为Base和Derived相关 ``` 在上例中,`static_cast`将`float`转换为`int`时,编译器会执行数值截断(属于降低精度转换),并可能生成警告[^3]。 #### 2. **reinterpret_cast的含义** `reinterpret_cast`用于**无关类型之间的转换**,这些类型在逻辑上无关联(如指针到整数或不同类型指针之间的转换)。它直接重新解释原始数据的比特位,而不进行任何值转换或类型检查。 - **核心特性**: - 不执行类型检查或值调整;仅简单地将原始比特位视为目标类型[^1]。 - 常用于低级编程,如硬件操作、序列化或处理内存地址(如指针转整数)。 - 高度不安全:可能导致未定义行为(UB),如果类型不兼容[^2]。 - **示例**: ```cpp int number = 42; // 将int指针转换为void指针,再转换为char指针(无关类型) void* voidPtr = reinterpret_cast<void*>(&number); char* charPtr = reinterpret_cast<char*>(voidPtr); // 直接重新解释比特位:charPtr指向number的内存 // 将整数视为函数指针(危险操作!) typedef void (*FuncPtr)(); FuncPtr func = reinterpret_cast<FuncPtr>(0x1000); // 假设0x1000是函数地址 ``` 在此例中,`reinterpret_cast`直接操作比特位,但未验证`0x1000`是否真是有效函数地址,可能导致崩溃。 #### 3. **关键区别总结** 基于引用[1]和[2],两者的核心差异在于语义和安全性: - **转换逻辑**: - `static_cast`:尝试执行“有意义”的转换(如数值计算或类层次调整),编译器可能插入额外代码(如截断浮点数)。 - `reinterpret_cast`:仅改变编译器的类型解释,不修改数据(比特位保持相同)。例如,将指针地址直接视为整数:如果`p`是指针,`reinterpret_cast<uintptr_t>(p)`返回其内存地址值[^1]。 - **安全性**: - `static_cast`相对安全:编译器会检查可行性(如类层次是否兼容),无效转换会引发编译错误。 - `reinterpret_cast`高度不安全:绕过类型系统,可能导致运行时未定义行为(如访问无效内存)[^2]。 - **使用场景**: - 优先使用`static_cast`:用于常见类型转换(如数值、多态类)。 - 谨慎使用`reinterpret_cast`:仅在低级操作(如系统编程)且无其他选择时才用。 #### 4. **安全警告** - `static_cast`在降低精度时(如`double`转`int`)可能丢失数据,但编译器通常给出警告[^3]。 - `reinterpret_cast`应避免:它破坏了类型安全,C++标准不保证其行为可移植。仅在必要时(如处理硬件寄存器)使用,并确保目标环境兼容。 数学上,`reinterpret_cast`的效果类似于直接操作比特序列:给定变量$x$(类型$T$),`reinterpret_cast<U>(x)`生成新值$y$(类型$U$),其中$y$的比特位与$x$相同,即: $$ \text{bits}(y) = \text{bits}(x) $$ 但$y$的类型语义可能完全无效[^1]。 #### 最佳实践 - 首选`static_cast`:它更安全且可读性高。 - 测试`reinterpret_cast`:在关键代码中,添加静态断言(如`static_assert(sizeof(int) == sizeof(float))`)来预防未定义行为。 - 避免C风格转换:旧式转换(如`(int*)ptr`)结合了`static_cast`、`reinterpret_cast`和`const_cast`的语义,易引发错误。 如果仍有疑问,提供具体代码片段可进一步诊断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值