C++学习知识点记录1

1. auto与decltype区别

auto

  • 作用:根据初始化表达式自动推导变量的实际类型。
  • 使用场景:
    1、简化复杂类型的声明(如迭代器、lambda表达式等)。
    2、类型不重要或类型可能会变化时。
    3、希望变量具有与初始化表达式相同的类型。
auto x = 42;           // x 的类型为 int
auto y = 3.14;         // y 的类型为 double
auto z = add(1, 2);    // z 的类型由 add 返回值决定(int)

const int &a = x;
auto b = a;            // b 的类型为 int(去掉了 const 和引用)

注:auto 会忽略顶层的 const 和引用。

decltype

  • 作用:获取表达式的确切类型(包括引用、const 等修饰符)。
  • 使用场景:
    1、需要保留表达式的引用或 const 属性。
    2、编写泛型代码时,推导某个表达式的类型。
    3、在模板元编程中用于类型操作。
int i = 1024;
int &j = i;

decltype(i) x = 2048;      // x 的类型为 int
decltype(j) y = i;         // y 的类型为 int&(保留了引用)

const int &ci = i;
decltype(ci) z = i;        // z 的类型为 const int&

对比总结

特性autodecltype
推导依据初始化表达式的值表达式的类型(包括引用、const 等)
是否保留引用否(退化为值类型)是(保留引用)
是否保留 const否(退化为非 const)是(保留 const)
适用场景简化类型声明、通用类型推导泛型编程、精确类型控制

例子

template <typename T>
void foo(T& val) {
    auto x = val;          // x 是 T 的值类型(去掉引用和 const)
    decltype(val) y = val; // y 是 T&(保留引用)
}

结论

  • 如果你只关心“这个表达式的值是什么类型”,用 auto
  • 如果你需要“完全保留表达式的类型特性(如引用、const)”,用 decltype

2、左值和右值

定义

  • 右值:临时存储对象,没有确定的内存位置。
  • 左值:除右值以外的是左值。

举例

int a = 10; // 'a' 是一个左值,'10' 是一个右值
int* p = new int(20); // '*p' 是一个左值

函数返回值为右值。

int foo() {return 2;}

int main()
{
    foo() = 2; // error! foo()返回值是右值,不能给右值赋值

    return 0;
}

字面量和表达式为右值。

int var;
var = 4;    // var是一个左值,左值可以赋值
4 = var;       // 错误! '4' 是一个右值,不能赋值
(var + 1) = 4; // 错误! 'var + 1'是一个表达式,是右值,不能赋值

函数返回值也可以为左值。

int globalvar = 20;

int& foo()
{
    return globalvar;    // 函数返回左值引用
}

int main()
{
    foo() = 10;   // 左值引用可以赋值
    return 0;
}

左值可以转换为右值,但是右值不能被转换成左值。

int a = 1;     // a 是左值
int b = 2;     // b 是左值
int c = a + b; // + 需要右值,所以 a 和 b 被转换成右值
               // + 返回右值

不能将右值赋给左值引用。

std::string& sref = std::string();   // error!
int &ref = 1; // error1
const int &ref1 = 1; // 正确,增加了const限定符

3、四种类型强制转换

static_cast

static_cast用于基本数据类型的转换,如整型、浮点型之间的转换,也可以用于具有继承关系的类对象之间的转换。它不能进行无关类型之间的转换,例如不能将一个完全不相关的类指针转换为另一个类指针。

double d = 3.14;
int i = static_cast<int>(d); // 将double转换为int

dynamic_cast

dynamic_cast主要用于涉及类层次结构的安全向下转型(downcasting),即从基类指针或引用转换为派生类指针或引用。它在运行时检查转换的有效性,如果转换是安全的,则成功;否则,对于指针返回nullptr,对于引用则抛出std::bad_cast异常。

class Base { virtual void dummy() {} };
class Derived : public Base {};
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b); // 如果b实际指向的是Derived对象,转换成功

const_cast

const_cast用于添加或移除变量的constvolatile属性。这是唯一可以改变变量是否为const的方式,但需要注意的是,如果你使用const_cast移除了某个变量的const属性并尝试修改它,而该变量实际上是定义为const的,那么这个行为是未定义的。

const int a = 10;
int* b = const_cast<int*>(&a); // 移除'a'的const属性

reinterpret_cast

reinterpret_cast是最粗略的类型转换,它基本上只是重新解释了给定的比特模式,而不进行任何类型的检查或转换逻辑。它可以用于指针间、指针与整数间的转换,但这种转换非常危险,除非你确切知道你在做什么,否则不推荐使用。

int a = 0x12345678;
int* p = &a;
long long* q = reinterpret_cast<long long*>(p); // 强制转换为不同类型的指针

这四种类型转换提供了不同的功能和安全性级别。通常建议尽可能使用static_castdynamic_castconst_cast,因为它们提供了编译时期的一些类型检查,并且意图更加明确。而reinterpret_cast由于其潜在的危险性,应该谨慎使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值