new

在C++中,new 是用于动态分配内存并创建对象的关键字。当使用 new 创建对象时,对象被分配在堆内存中,而不是栈内存中。

使用 new 的主要原因包括:

  • 动态内存分配: new 允许在程序运行时动态地分配内存空间,而不需要在编译时确定对象的大小。这对于需要灵活管理内存的情况非常有用,例如当对象的大小在运行时才能确定时,或者需要在程序的不同部分共享对象时。

  • 对象的生命周期: 使用 new 创建的对象存储在堆内存中,其生命周期由程序员显式管理。这意味着对象在程序员释放内存之前不会被销毁,因此可以在程序的任何地方访问对象。相比之下,栈上的对象的生命周期是由其作用域决定的,一旦超出作用域,对象就会被销毁。

  • 返回指针: new 返回一个指向新分配对象的指针,这允许在需要时以指针的形式传递对象,并在需要时释放对象的内存。这在函数返回对象时特别有用,因为函数返回值的大小可能是动态的,或者需要在函数外部持续存在。

尽管使用 new 具有灵活性和控制权,但也需要小心管理动态分配的内存,以防止内存泄漏和悬空指针等问题。因此,在使用 new 分配内存时,通常需要配合使用 delete 来释放内存,以避免内存泄漏。

this指针

在C++中,this 指针是一个特殊的指针,它指向当前对象。

this 指针通常在类的成员函数中使用,用于访问当前对象的成员变量和成员函数。

this 指针主要有以下几个用途:

  1. 区分局部变量和成员变量: 当成员函数的参数名和成员变量名相同时,可以使用 this 指针来明确指示要访问的是成员变量而不是局部变量。例如:
class MyClass {
public:
int x;
void setValue(int x) {
this->x = x; // 使用this指针访问成员变量
}
};
  1. 在成员函数中返回对象本身: 当成员函数需要返回当前对象本身时,可以使用 return *this; 。这种技术常用于实现链式调用。例如:
MyClass obj;
obj.setValue(10).print(); // setValue函数返回*this,可以直接调用print函数
  1. 在构造函数和析构函数中访问当前对象: 在构造函数和析构函数中,可以使用 this 指针来访问当前对象。这在需要在构造函数和析构函数中对当前对象进行一些额外操作时很有用。

纯虚函数

在C++中,纯虚函数是一个在基类中声明但没有实现的虚函数。

纯虚函数的作用主要体现在以下几个方面:

  • 接口定义: 纯虚函数可以用来定义接口,即定义一个接口类,而不提供具体的实现。派生类必须实现这些纯虚函数,从而确保派生类都提供了相同的接口,但具体的实现可以根据派生类的需求来实现。

  • 多态性: 纯虚函数可以使得基类指针或引用在运行时指向派生类对象,并调用派生类中相应的实现。这样可以实现多态性,提高了代码的灵活性和可扩展性。

  • 抽象类: 包含纯虚函数的类被称为抽象类,它们无法直接创建对象,只能作为基类来派生出其他类。抽象类的存在主要是为了提供一种接口,由派生类来实现具体的行为。

  • 框架设计: 在框架设计中,可以使用纯虚函数来定义一些必须由客户程序实现的操作,从而定义了一个框架的结构,并允许客户程序根据自己的需求来定制具体的行为。

总之,纯虚函数的作用在于提供了一种机制,使得类可以定义接口、实现多态性、构建抽象类以及设计框架等。

函数指针

函数指针是指向函数的指针变量。

在C++中,函数也是一种数据类型,因此可以像其他数据类型一样,通过指针来引用和传递函数。函数指针可以存储函数的地址,并且可以通过调用该指针来间接调用函数。

函数指针的声明方式与普通指针类似,但是要在指针名前面加上函数的返回类型和参数列表,以表示该指针指向的函数的类型。函数指针的语法通常如下:

返回类型 (*指针变量名)(参数列表);

例如,假设有一个函数 void printMessage(const char* message),那么可以声明一个指向该函数的指针如下:

void (*ptr)(const char*);

函数指针的主要用途包括回调函数、动态选择调用的函数等。通过函数指针,可以实现更加灵活和多样化的函数调用方式,提高了程序的可扩展性和可维护性。

cpp匿名对象

C++中的匿名对象是指在不使用变量名的情况下创建的临时对象。

它们通常用于作为函数的参数传递或作为表达式的一部分。

匿名对象没有变量名,因此不能在其他地方引用,一旦超出了当前作用域,匿名对象就会被销毁。

例如:

class MyClass {
public:
void print() {
std::cout << "Printing from MyClass" << std::endl;
}
};

int main() {
// 创建匿名对象,并调用成员函数
MyClass().print(); // 这里的 MyClass() 就是一个匿名对象
return 0;
}

在上面的例子中,MyClass() 创建了一个匿名对象,然后调用了它的 print() 成员函数。

STL

deque

C++中的deque(双端队列)是一种数据结构,它允许在两端进行高效的元素插入和删除操作。deque是由多个连续的存储块组成的,每个存储块通常是一个固定大小的数组,这些数组按需动态分配和释放内存。这种设计使得deque可以高效地支持在队列的两端进行元素的插入和删除操作,而不会像向量(vector)那样在中间插入或删除元素时产生大量的数据搬移。

deque可以在常量时间内执行以下操作:

从队列的前端或后端插入或删除一个元素。
访问队列的第一个或最后一个元素。
由于deque使用了多个存储块,所以在内存中的布局是不连续的。这意味着deque不支持通过指针或迭代器进行随机访问,因为元素在内存中的位置不是连续的。但是,deque仍然可以通过迭代器进行顺序访问,并且支持在常量时间内查找、插入和删除元素。

总之,deque提供了一种灵活的双端队列实现,可以在两端高效地进行元素的插入、删除和访问操作,并且在插入和删除元素时不会造成大量的数据搬移。

“多个连续的存储块”指的是deque内部的数据结构。deque通常由多个存储块组成,每个存储块是一个固定大小的数组,用于存储元素。这些存储块在逻辑上是连续的,但在内存中的布局是不连续的。换句话说,deque的每个存储块在内存中都是单独分配的,它们之间可能存在一定的间隔。

由于deque的每个存储块都是一个固定大小的数组,因此它们具有相同的容量。当需要插入或删除元素时,deque可以根据需要动态地分配或释放存储块,以保持合适的容量。这种设计使得deque在两端执行元素插入和删除操作时具有良好的性能,因为它可以在常量时间内执行这些操作,而不会像向量(vector)那样需要重新分配整个内存空间。