C++面试题
问题: 什么是左值(lvalue)和右值(rvalue)?请举例说明。
答案: 在C++中,左值(lvalue)指的是具有标识符(可寻址)的表达式,而右值(rvalue)指的是不具有标识符(不可寻址)的表达式。简单来说,左值表示一个可以被引用的对象,而右值表示一个临时的、不可修改的值。例如:
int x = 42; // x是左值,因为它具有标识符 int y = x + 5; // x + 5是右值,因为它是一个临时值 int* ptr = &x; // &x是右值,因为它是一个临时的内存地址
问题: 什么是移动语义(Move Semantics)?它在C++中的作用是什么?
答案: 移动语义是一种优化技术,旨在避免不必要的对象复制操作,提高程序的性能。它通过将资源的所有权从一个对象转移到另一个对象,而不是进行传统的复制操作,来实现高效的对象管理。
在C++11中引入了移动语义,通过移动构造函数和移动赋值运算符来支持。移动构造函数用于将临时对象的资源转移到目标对象,而移动赋值运算符用于将一个对象的资源转移到另一个对象。这样可以避免不必要的内存分配和复制操作,提高程序的效率。
问题: 什么是智能指针(Smart Pointer)?它们在C++中的作用是什么?
答案: 智能指针是一种用于管理动态分配的内存的C++类模板。它们提供了自动的内存管理,帮助避免内存泄漏和悬挂指针(dangling pointer)等问题。
C++标准库中提供了三种智能指针:
std::unique_ptr
、std::shared_ptr
和std::weak_ptr
。std::unique_ptr
表示独占所有权的指针,std::shared_ptr
表示共享所有权的指针,而std::weak_ptr
则用于解决std::shared_ptr
的循环引用问题。智能指针通过在对象销毁时自动释放内存,并在不再需要时自动删除指针,简化了内存管理的工作,提高了程序的安全性和可靠性。
问题: 什么是模板(Template)?请举例说明如何定义和使用模板函数。
答案: 模板是一种C++的特性,用于实现泛型编程,即编写可重用的通用代码。模板允许定义泛型函数或类,可以在不同的数据类型上进行实例化。
下面是一个示例模板函数的定义和使用:
template <typename T> T maximum(T a, T b) { return (a > b) ? a : b; } int main() { int maxInt = maximum(5, 10); // 使用模板函数实例化int类型 double maxDouble = maximum(3.14, 2.71); // 使用模板函数实例化double类型 return 0; }
在上面的示例中,
maximum
是一个模板函数,它可以接受任意类型的参数a
和b
。通过使用typename
或class
关键字来声明模板参数类型,可以在编译时根据实际的参数类型生成对应的函数代码。在main
函数中,我们使用模板函数maximum
分别实例化了int
类型和double
类型的调用。问题: 什么是虚拟析构函数(Virtual Destructor)?为什么需要虚拟析构函数?
答案: 虚拟析构函数是在基类中声明为
virtual
的析构函数。它在处理对象的多态性时起着重要的作用。当基类指针指向派生类对象并通过该指针删除对象时,如果基类的析构函数不是虚拟的,那么只会调用基类的析构函数,而不会调用派生类的析构函数。这可能导致派生类资源没有得到释放,从而引发内存泄漏等问题。
通过将基类的析构函数声明为虚拟的,可以确保在删除派生类对象时正确调用派生类的析构函数,从而释放所有相关资源。
例如:
class Base { public: virtual ~Base() { // 基类析构函数 } }; class Derived : public Base { public: ~Derived() override { // 派生类析构函数 } }; int main() { Base* basePtr = new Derived(); delete basePtr; // 调用派生类的析构函数 return 0; }