1.const_cast
const_cast 是 C++ 中的一种强制类型转换运算符,用于将指向非常量对象的指针或引用转换为指向常量对象的指针或引用,或者将指向常量对象的指针或引用转换为指向非常量对象的指针或引用。
const_cast 的作用是去除指针或引用类型的常量限定符,以便进行一些特殊的操作。例如,在某些情况下,你可能需要修改一个常量对象的值,但是由于该对象是常量,无法直接修改。此时,你可以使用 const_cast 去除该对象的常量限定符,以便修改其值。需要注意的是,这种操作可能会导致未定义的行为,因此应该谨慎使用。
以下是一个使用 const_cast 的例子,用于修改一个常量对象的值:
void modify(const int* ptr) {
int* non_const_ptr = const_cast<int*>(ptr);
*non_const_ptr = 123;
}
int main() {
const int x = 456;
modify(&x);
std::cout << "x = " << x << std::endl; // 输出结果为 "x = 123"
return 0;
}
在上面的例子中,modify 函数接受一个指向常量整数的指针,并使用 const_cast 将其转换为指向非常量整数的指针,以便修改该整数的值。然后,在 main 函数中,我们将一个常量整数的地址传递给 modify 函数,并发现该整数的值已经被修改为 123。
2.static_cast
static_cast 是 C++ 中的一种强制类型转换运算符,用于将一个表达式的类型转换为另一个类型,但是只能用于有明确定义的类型转换,且转换的安全性由程序员自行保证。
static_cast 可以用于以下类型转换:
数值类型之间的转换,例如将 int 转换为 double。
指针类型之间的转换,例如将 void* 指针转换为特定类型的指针。
引用类型之间的转换,例如将 int& 引用转换为 double& 引用。
将指向基类的指针或引用转换为指向派生类的指针或引用,或者将指向派生类的指针或引用转换为指向基类的指针或引用。
需要注意的是,static_cast 的安全性由程序员自行保证,如果类型转换不合法,可能会导致未定义的行为。因此,在使用 static_cast 进行类型转换时,需要仔细检查代码,确保类型转换的正确性。
以下是一个使用 static_cast 进行类型转换的例子:
int main() {
int x = 123;
double y = static_cast<double>(x);//如果不加static_cast,会编译报错
std::cout << "x = " << x << ", y = " << y << std::endl;//x = 123, y = 123
return 0;
}
在上面的例子中,我们将整数变量 x 转换为双精度浮点数类型 double,并将转换后的值赋给变量 y。需要注意的是,由于 static_cast 是一种静态类型转换,因此编译器在编译时就会检查类型转换的合法性。
3.reinterpret_cast
reinterpret_cast 是 C++ 中的一种强制类型转换运算符,用于将一个指针或引用类型转换为另一个指针或引用类型,但是它不会进行任何类型检查或调整,因此非常危险,只有在必要的情况下才应该使用。
reinterpret_cast 可以用于以下类型转换:
将一个指针类型转换为另一个指针类型,例如将 int* 指针转换为 char* 指针。
将一个指针类型转换为一个整数类型,例如将 void* 指针转换为 int 类型。
将一个整数类型转换为一个指针类型,例如将 int 类型转换为 void* 指针。
将一个指针类型转换为一个整数类型,再将该整数类型转换为另一个指针类型,例如将 char* 指针转换为 int 类型,再将该 int 类型转换为 float* 指针。
需要注意的是,reinterpret_cast 的安全性非常低,因为它不会进行类型检查或调整,因此可能会导致未定义的行为。因此,在使用 reinterpret_cast 进行类型转换时,必须确保转换的正确性,并且仅在必要的情况下才应该使用。
以下是一个使用 reinterpret_cast 进行类型转换的例子:
int main() {
int x = 123;
int* p = &x;
char* c = reinterpret_cast<char*>(p);
std::cout << "x = " << x << ", *p = " << *p << ", *c = " << *c << std::endl;
return 0;
}
在上面的例子中,我们将整数变量 x 的地址赋值给整型指针变量 p,然后使用 reinterpret_cast 将 p 指针转换为字符型指针 c,最后输出 x、*p 和 *c 的值。需要注意的是,由于 reinterpret_cast 不会进行任何类型检查或调整,因此在输出 *c 的值时,可能会导致未定义的行为。
4.dynamic_cast
dynamic_cast 是 C++ 中的一种类型转换运算符,用于将基类的指针或引用转换为派生类的指针或引用。它主要用于动态类型识别,可以在运行时检查对象的实际类型,如果类型转换失败,返回 nullptr。
dynamic_cast 的使用方式如下:
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void foo() {}
};
int main() {
Base* p_base = new Derived();
Derived* p_derived = dynamic_cast<Derived*>(p_base);
if (p_derived != nullptr) {
p_derived->foo();
} else {
std::cout << "dynamic_cast failed" << std::endl;
}
delete p_base;
return 0;
}
在上面的代码中,我们定义了两个类 Base 和 Derived,其中 Derived 是 Base 的派生类。然后,我们创建了一个指向 Derived 类型对象的 Base 指针 p_base,并使用 dynamic_cast 将其转换为 Derived 类型的指针 p_derived。由于对象实际上是一个 Derived 类型的对象,因此转换成功,并且我们可以通过 p_derived 调用 foo 函数。最后,我们释放了 p_base 指向的内存。
需要注意的是,dynamic_cast 只能用于指针或引用类型之间的转换,不能用于数值类型之间的转换。此外,使用 dynamic_cast 进行类型转换时,需要确保基类和派生类之间存在继承关系,否则可能会导致编译错误或者未定义的行为。
5.delete
delete 是一个 C++11 引入的关键字,用于删除某个函数或者禁用某个特定的操作。具体来说,delete 有以下两种用法:
1.删除函数:在函数声明或定义中,使用 delete 关键字可以删除某个函数,使得该函数不能被调用。例如:
class Foo {
public:
void bar() = delete; // 删除 bar 函数
};
2.禁用操作:在类的定义中,使用 delete 关键字可以禁用某个特定的操作,例如拷贝构造函数、拷贝赋值函数或移动构造函数等。例如:
class Foo {
public:
Foo(const Foo&) = delete; // 禁用拷贝构造函数
Foo& operator=(const Foo&) = delete; // 禁用拷贝赋值函数
Foo(Foo&&) = delete; // 禁用移动构造函数
Foo& operator=(Foo&&) = delete; // 禁用移动赋值函数
};
在上面的代码中,我们使用 delete 关键字禁用了拷贝构造函数、拷贝赋值函数和移动构造函数,使得这些操作不能被执行。
需要注意的是,使用 delete 关键字可以提高程序的安全性和可靠性,但需要根据具体的需求和情况进行选择
3.删除数组元素:在动态数组的元素类型中,使用 delete 关键字可以删除数组的元素,例如:
int* arr = new int[10];
delete arr[5]; // 删除第 6 个元素
在上面的代码中,我们使用 delete 关键字删除了数组 arr 的第 6 个元素。
4.在 C++ 中,我们可以使用 new 运算符来动态地分配内存,并返回指向分配内存的指针。当我们使用完这些内存后,需要使用 delete 运算符来释放这些内存,并将指针置为 nullptr。以下是一个使用 new 和 delete 的示例代码:
int* ptr = new int(10); // 分配内存并初始化为 10
std::cout << "ptr = " << *ptr << std::endl; // 输出指针指向的值
delete ptr; // 释放内存
ptr = nullptr; // 将指针置为 nullptr
在上面的代码中,我们使用 new 运算符分配了一个 int 类型的内存,并将其初始化为 10。然后,我们输出指针指向的值,并使用 delete 运算符释放这些内存,并将指针置为 nullptr。
需要注意的是,使用 delete 运算符删除指针时,需要确保指针指向的内存已经被分配,并且只能删除由 new 运算符分配的内存,不能删除由其他方式分配的内存。另外,在使用 delete 运算符时,如果我们忘记将指针置为 nullptr,可能会导致悬挂指针的问题,因此在释放内存后,应该将指针置为 nullptr,以避免这种问题的发生。
6.static
static 是一个 C++ 中常用的关键字,其作用和用法有多种,包括以下几个方面:
1.静态变量:使用 static 关键字可以定义静态变量,静态变量的生命周期与程序的生命周期相同,它们只会被初始化一次,可以用来保存全局状态或者计数器。例如:
void foo() {
static int count = 0; // 定义静态变量
count++;
std::cout << "count = " << count << std::endl;
}
int main() {
foo(); // count = 1
foo(); // count = 2
foo(); // count = 3
return 0;
}
在上面的代码中,我们使用 static 关键字定义了静态变量 count,并在函数 foo 中使用它来实现计数器的功能。静态变量 count 的生命周期与程序的生命周期相同,它只会被初始化一次,可以用来保存全局状态或者计数器。
2.静态函数:使用 static 关键字可以定义静态函数,静态函数可以在类的内部使用,但不能被类的对象调用,只能被类的名称直接调用。静态函数通常用于实现工具函数或者私有函数,例如:
class Foo {
public:
static int add(int x, int y) { // 定义静态函数
return x + y;
}
void bar() {
// do something
}
};
int main() {
int result = Foo::add(1, 2); // 调用静态函数
std::cout << "result = " << result << std::endl;
Foo foo;
foo.bar(); // 调用成员函数
return 0;
}
在上面的代码中,我们使用 static 关键字定义了静态函数 add,并在类 Foo 的内部使用它来实现加法运算。静态函数 add 可以通过类的名称直接调用,而不需要通过类的对象调用。
3.静态成员变量:使用 static 关键字可以定义静态成员变量,静态成员变量是该类的所有对象所共享的,可以用来保存类的全局状态或者计数器。静态成员变量的生命周期与程序的生命周期相同,它们只会被初始化一次,可以用来保存全局状态或者计数器。例如:
class Foo {
public:
static int count; // 定义静态成员变量
};
int Foo::count = 0; // 初始化静态成员变量
int main() {
Foo foo1, foo2, foo3;
foo1.count++;
foo2.count++;
foo3.count++;
std::cout << "count = " << Foo::count << std::endl;
return 0;
}
在上面的代码中,我们使用 static 关键字定义了静态成员变量 count,并在类外初始化它。静态成员变量 count 是该类的所有对象所共享的,可以用来保存类的全局状态或者计数器。
需要注意的是,为了确保静态成员变量的唯一性和正确性,我们需要在类外对其进行定义和初始化。这是因为静态成员变量的定义和初始化只能在全局作用域中进行,而不能在类的内部进行。
7.const
C++ 中 const 关键字可以用于以下几种情况:
1.修饰变量:const 可以用于修饰变量,表示该变量的值不可修改。例如:
const int a = 10; // 定义一个常量 a,不可修改其值
int const b = 20; // 与上面等价,修饰符放在类型前或后都可以
2.修饰函数参数:const 可以用于修饰函数参数,表示函数内部不会修改该参数的值。例如:
void func(const int a) { // 定义一个参数 a,不可修改其值
// ...
}
3.修饰函数返回值:const 可以用于修饰函数返回值,表示返回值是常量,不可修改。例如:
const int func() { // 定义一个返回值为常量的函数
// ...
}
4.修饰成员函数:const 可以用于修饰成员函数,表示该函数不会修改对象的状态。例如:
class MyClass {
public:
void func() const { // 定义一个常量成员函数,不会修改对象的状态
// ...
}
};
5.修饰成员变量:const 可以用于修饰成员变量,表示该变量的值是常量,不可修改。例如:
class MyClass {
public:
const int a = 10; // 定义一个常量成员变量 a,不可修改其值
int const b = 20; // 与上面等价,修饰符放在类型前或后都可以
};
6.修饰指针:const 可以用于修饰指针,表示该指针指向的值不可修改或该指针不可修改。例如:
const int* p1; // 定义一个指向常量的指针,不可修改指针指向的值
int const* p2; // 与上面等价,修饰符放在类型前或后都可以
int* const p3; // 定义一个常量指针,不可修改指针本身的值
const int* const p4; // 定义一个指向常量的常量指针,不可修改指针本身的值,也不可修改指针指向的值
需要注意的是,使用 const 关键字可以提高代码的可读性和可维护性,可以避免代码中的一些潜在问题,例如不小心修改常量、误操作指针等。因此,在编写代码时,应该尽可能地使用 const 关键字来修饰常量、指针、函数参数、函数返回值等。