必须知道的C++基础

1. 什么是 C++?C++ 的优点是什么?

C++简介及其优点

C++是一种通用的编程语言,最初由Bjarne Stroustrup于1979年在贝尔实验室开发,目的是作为C语言的扩展,支持面向对象的编程(OOP)。C++支持过程式编程、面向对象编程、泛型编程等多种编程范式。

C++的主要特点:

  • 面向对象:C++引入了类(class)和对象(object)的概念,支持封装、继承和多态等面向对象的特性。
  • 多范式:C++不仅支持面向对象编程,还支持过程式编程和泛型编程,灵活性非常高。
  • 低级操作:C++允许开发者直接操作硬件和内存,能够提供高效的性能,适用于需要高性能的应用场景。
  • 标准库:C++提供了强大的标准库(STL,Standard Template Library),包括容器类、算法、迭代器等,使得编程更加高效和简洁。
  • 高性能:C++编译后的代码执行速度非常快,适合进行性能要求高的系统开发,如操作系统、游戏引擎、实时系统等。

C++的优点:

  1. 性能高效
    C++是一种编译语言,通过编译生成本地机器码,运行时效率高。相比于解释型语言(如Python),C++可以更直接地操作硬件和内存。

  2. 灵活性强
    C++支持多种编程范式(面向对象、过程式、泛型编程),能够根据项目需求选择最合适的编程方法。

  3. 面向对象编程(OOP)
    C++支持类和对象的概念,能够更好地管理复杂系统。通过封装、继承和多态,C++帮助开发者构建可扩展和易维护的代码。

  4. 内存控制
    C++允许开发者手动管理内存(通过newdelete),在需要时能够直接优化内存分配和回收。虽然这增加了编程的复杂性,但也提供了更高的控制权。

  5. 广泛应用
    C++在各个领域都有广泛的应用,如操作系统开发、游戏开发、嵌入式系统、金融系统、图像处理等。它的高效性和灵活性使其在很多行业中都占有重要地位。

  6. 强大的标准库(STL)
    C++的标准模板库(STL)提供了大量的预先构建的数据结构和算法(如向量、链表、映射、排序、查找等),极大地提高了开发效率。

  7. 跨平台支持
    C++的代码能够在不同的平台上运行,只要对应平台提供了C++的编译器。对于需要跨平台开发的项目,C++是一个非常理想的选择。

2. C++ 中有哪些数据类型?

C++ 中主要的数据类型有:

  1. 基本数据类型

    • int:整数类型
    • float:单精度浮点数
    • double:双精度浮点数
    • char:字符类型
    • bool:布尔类型(truefalse
  2. 修饰符

    • short:短整型
    • long:长整型
    • long long:更长的整型
    • unsigned:无符号类型(unsigned int 等)
    • signed:有符号类型(默认为 signed
  3. 派生数据类型

    • 数组:同一数据类型元素的集合
    • 指针:存储地址的变量
    • 引用:变量的别名
  4. 抽象数据类型

    • struct:结构体
    • class:类
    • union:共用体
    • enum:枚举类型
  5. 空类型

    • void:无类型,通常用于函数返回类型
  6. 类型别名

    • typedefusing:为现有类型创建别名

3. 定义‘std’?

‘std’ 也叫做标准命名空间,或者可以理解为命名空间。命令 using namespace std 会告知编译器将 std 命名空间中的所有内容引入到全局命名空间中,这样我们就可以直接使用 coutcin,而不需要写 std::coutstd::cin

4. 什么是引用?

引用是一个已初始化的别名,用于指向一个已有的变量。通过引用,可以直接操作原始变量的值。

特点:

  • 必须在声明时初始化,且不能改变引用的对象。
  • 引用与原变量共享同一内存地址。
  • 常用于函数参数传递,避免拷贝,提高效率。

示例:

int a = 10;
int& ref = a;  // ref是a的引用
ref = 20;  // 通过引用修改a的值
// a的值现在是20

常量引用(const引用)用于引用不可修改的对象。

const int& ref = a;  // ref是a的常量引用

5. 什么是值传递和引用传递?

1. 值传递(Pass by Value)

  • 定义:函数接收的是实参的副本,修改副本不会影响原始数据。
  • 特点:会复制数据,性能开销较大,尤其是传递大型对象时。

示例:

void func(int x) {
    x = 20;  // 修改x不会影响实参
}

int main() {
    int a = 10;
    func(a);
    // a的值仍为10
}

2. 引用传递(Pass by Reference)

定义:函数接收的是实参的引用,修改参数会直接修改实参。

特点:避免了数据拷贝,常用于修改实参或传递大型对象。

void func(int& x) {
    x = 20;  // 修改x会影响实参
}

int main() {
    int a = 10;
    func(a);
    // a的值变为20
}

6. 什么是 C++ 中的“token”?

token 是程序中最小的独立元素,编译器可以理解它。一个 token 包括以下内容:

  • 关键词:对编译器具有特殊意义的词。
  • 标识符:持有唯一值/身份的元素。
  • 常量:在程序执行过程中始终保持不变的值。
  • 字符串:包含同质数据序列。
  • 特殊符号:具有特殊含义,不能用于其他目的的符号,如 [] () {} ; * = #。
  • 操作符:用于对操作数执行运算的符号。

7. C 和 C++ 之间的区别?

CC++
是一种过程式编程语言,不支持类和对象是过程式与面向对象相结合的编程语言,支持类和对象
不支持 OOPs 概念,如多态、数据抽象、封装等支持多种 OOPs 概念
不支持函数重载和操作符重载支持函数重载和操作符重载
是一种面向函数的语言是一种面向对象的语言

8. structclass 有什么区别?

Aspectstructclass
默认访问修饰符成员默认是公共的成员默认是私有的
内存分配可以分配在栈或堆上可以分配在栈或堆上
继承支持继承(公共、保护或私有访问)支持继承(公共、保护或私有访问)
用途通常用于简单的数据结构或数据组合适用于复杂对象,可能包括方法、构造函数和析构函数

9. 引用和指针有什么区别?

引用指针
引用的值不能重新分配指针的值可以重新分配
引用不能持有空值,必须指向一个已存在的值指针可以指向空值,被称为 nullptr 或空指针
访问类/结构体成员时使用 ‘.’访问类/结构体成员时使用 ‘->’
引用的内存位置可以直接访问指针的内存位置必须通过解引用 * 来访问

10. 函数重载和操作符重载有什么区别?

函数重载操作符重载
定义多个同名函数,但每个函数的参数不同重新定义现有操作符的意义
通过改变函数参数的数量或类型来实现重载使已有操作符在特定上下文中具有不同的行为
例如:int add(int a, int b); int add(double a, double b);例如:class Complex { Complex operator+(const Complex& other); }

11. 数组和列表有什么区别?

数组列表
数组是存储在连续内存位置的同质数据类型,大小固定列表是通过指针将元素连接在一起,大小动态
数组的大小是静态的,创建后不能改变列表是动态的,可以根据需要调整大小
数组占用的内存较少列表占用更多内存,因为它需要存储元素和指针的内存

12. while 循环和 do-while 循环有什么区别?

while 循环do-while 循环
while 是一种入口控制循环,先判断条件,再执行循环体do-while 是一种出口控制循环,先执行循环体,后判断条件
如果条件不成立,循环体将不会执行即使条件不成立,循环体也会至少执行一次

13. 前缀和后缀运算符有什么区别?

前缀运算符后缀运算符
运算符位于操作数前面,先执行运算运算符位于操作数后面,先返回操作数再执行运算
前缀递增 ++i 执行时是右到左关联后缀递增 i++ 执行时是左到右关联

14. newmalloc() 有什么区别?

newmalloc()
new 是一个运算符,用于分配内存malloc 是一个函数,用于分配内存
new 会调用构造函数malloc 不会调用构造函数
new 的效率比 mallocmalloc 的效率较低
new 返回特定数据类型的指针malloc 返回 void* 类型的指针

15. 虚函数和纯虚函数有什么区别?

虚函数纯虚函数
虚函数是基类的成员函数,可以在派生类中重定义纯虚函数是基类的成员函数,在基类中只声明,在派生类中定义,防止基类成为抽象类
基类中的虚函数可以有定义纯虚函数在基类中没有定义,且声明时使用 = 0

16. C++ 中的类和对象是什么?

  1. 类(Class)
    • 类是 C++ 中用来定义对象的模板,包含数据成员(变量)和成员函数(方法)。
    • 类描述了一组具有相同属性和行为的对象。

示例:

   class Car {
   public:
       // 成员变量(属性)
       string brand;
       int year;

       // 成员函数(方法)
       void start() {
           cout << "The car is starting." << endl;
       }
   };
  1. 对象(Object)
    • 对象是类的一个实例,包含类中定义的数据和方法。
    • 每个对象根据类的定义在内存中创建,并且每个对象都有自己的数据。

示例:

   int main() {
       // 创建对象 myCar
       Car myCar;
       myCar.brand = "Toyota";
       myCar.year = 2020;
       myCar.start();  // 调用成员函数
   }
  • 对象通过类的构造和行为来实现具体功能。可以创建多个对象,每个对象独立存在,互不影响。

17. 什么是函数重写?

  1. 定义

    • 函数重写是子类重新定义父类中已有的虚函数的过程。
    • 重写的函数在子类中具有与父类函数相同的名称、返回类型和参数列表,但实现内容不同。
  2. 关键点

    • 虚函数(Virtual Function):父类中的函数必须是虚函数(使用 virtual 关键字声明),以允许在子类中进行重写。
    • 子类实现:子类必须重新定义该函数,提供不同的实现。
    • 多态:函数重写是实现运行时多态的关键。
  3. 示例

    #include <iostream>
    using namespace std;
    
    class Animal {
    public:
        virtual void sound() {  // 父类虚函数
            cout << "Animal makes a sound" << endl;
        }
    };
    
    class Dog : public Animal {
    public:
        void sound() override {  // 子类重写父类虚函数
            cout << "Dog barks" << endl;
        }
    };
    
    int main() {
        Animal* animal = new Dog();
        animal->sound();  // 输出 "Dog barks",多态表现
        delete animal;
        return 0;
    }
    
  4. 注意事项

    • 子类重写的函数应使用 override 关键字(可选,但推荐),以便编译器检查是否正确重写了父类的虚函数。
    • 如果父类函数没有被声明为虚函数,子类的函数将不会覆盖父类函数,而是隐藏父类的同名函数。

18. C++ 中的 OOPs 概念有哪些?

C++ 中的 OOPs 概念包括:

  • 类(Classes):是用户定义的数据类型
  • 对象(Objects):是类的实例
  • 抽象(Abstraction):显示必要的细节,隐藏不必要的部分
  • 封装(Encapsulation):将数据和方法封装在一起
  • 继承(Inheritance):类从其他类中继承属性和特性
  • 多态(Polymorphism):同一函数在不同情况下有不同的表现

19. 解释继承

  1. 定义

    • 继承是面向对象编程中的一种机制,允许一个类(子类)继承另一个类(父类)的属性和行为(成员变量和成员函数)。
    • 子类可以使用父类的公有成员,还可以扩展或重写父类的功能。
  2. 关键点

    • 继承关系:子类通过继承关系可以获得父类的属性和方法,继承是“is-a”关系。
    • 访问权限:继承有不同的访问权限,如公有继承、保护继承和私有继承。
    • 构造函数和析构函数:父类的构造函数不会被继承,但会在子类对象创建时调用。父类的析构函数也会在子类对象销毁时调用。
  3. 示例

    #include <iostream>
    using namespace std;
    
    // 父类
    class Animal {
    public:
        void eat() {
            cout << "Animal is eating" << endl;
        }
    };
    
    // 子类继承父类
    class Dog : public Animal {
    public:
        void bark() {
            cout << "Dog is barking" << endl;
        }
    };
    
    int main() {
        Dog dog;
        dog.eat();   // 子类可以访问父类的成员
        dog.bark();  // 子类自己的方法
        return 0;
    }
    
  4. 继承类型

    • 公有继承(public inheritance):子类继承父类的公有成员和保护成员,且保持原有的访问权限。
    • 保护继承(protected inheritance):子类继承父类的公有成员和保护成员,变为保护成员。
    • 私有继承(private inheritance):子类继承父类的所有成员,所有成员都变为私有。

20. 何时使用多重继承?

多重继承意味着一个派生类可以继承多个基类。当一个派生类需要结合多个父类的属性和行为时,可以使用多重继承。

  • 注意菱形继承问题:多个父类继承同一个基类时,可能会导致重复继承。
  • 使用虚继承(virtual inheritance) 可以避免菱形继承带来的二义性和冗余。

21. 什么是虚继承?

虚继承是一种确保派生类只继承一个基类成员变量的技术。当我们处理多重继承时,虚继承可以避免基类的多重实例出现在继承层次中。

22. 什么是多态?

多态是指同一操作在不同对象上有不同表现形式。在 C++ 中,多态分为两种:

  • 编译时多态:函数重载和操作符重载
  • 运行时多态:函数重写和虚函数

23. 编译时多态和运行时多态的区别?

编译时多态运行时多态
发生在程序编译时,执行较快发生在程序运行时,执行较慢
通过函数重载和操作符重载实现通过虚函数和函数重写实现

24. 构造函数是什么?

构造函数是类的特殊成员函数,名称与类名相同,用于初始化类的对象。构造函数有三种类型:

  • 默认构造函数:不带参数的构造函数,编译器会自动调用它。
  • 参数化构造函数:带参数的构造函数,必须显式调用。
  • 复制构造函数:用于通过同一类的另一个对象来初始化一个对象。

25. 析构函数是什么?

析构函数是类的成员函数,当类的对象超出作用域时,析构函数会删除对象并释放资源。析构函数的名称与类名相同,但前面有一个波浪符 ~

26. 虚析构函数是什么?

虚析构函数确保在通过基类指针删除派生类对象时,派生类的析构函数先被调用,从而防止内存泄漏。

27. 析构函数能否重载?如果能,请解释。

不能重载析构函数。在 C++ 中,每个类只能有一个析构函数,而且析构函数不能接受任何参数。

28. 指针可以进行哪些操作?

指针可以进行以下操作:

  • 指针的增/减
  • 将整数与指针相加/减
  • 比较相同类型的指针

29. “delete” 操作符的作用是什么?

delete 操作符用于删除通过 new 分配的动态内存,释放内存并清除对象。

30. delete[]delete 的区别是什么?

delete[]delete
用于删除数组对象用于删除单个对象
可以调用多个析构函数只能调用一个析构函数

31. 什么是友元类和友元函数?

友元类可以访问另一个类的私有和保护成员。友元函数可以访问类的私有、保护和公共数据成员。它不是类的成员函数,可以在类外部调用。

32. 溢出错误是什么?

溢出错误发生在数据超出了数据类型所能表示的范围时。例如,int 类型的范围是 -2,147,483,648 到 2,147,483,647,如果分配一个大于上限的值,就会发生溢出错误。

33. ::(作用域解析运算符)做什么?

作用域解析运算符 :: 用于访问类外部的全局变量,或引用类成员函数、命名空间中的元素。

34. C++ 中的访问修饰符有哪些?

C++ 中的访问修饰符有三种:

  • private:类外部无法访问
  • protected:只能在派生类中访问
  • public:类外部可以访问

35. 可以没有 main 函数编译程序吗?

是的,可以编译没有 main 函数的程序。例如,使用宏来定义 main 函数。

#include <stdio.h>
#define fun main
int fun(void) {
    printf("GeeksforGeeks");
    return 0;
}

36. 什么是 STL?

  1. 定义

    • STL(Standard Template Library)是 C++ 标准库的一部分,提供了常用的算法和数据结构模板。
    • STL 主要包括容器、算法、迭代器和函数对象等组件,用于提高开发效率和代码复用性。
  2. STL 组件

    • 容器(Containers):用于存储数据的对象,如 vector, list, map, set 等。
      • 顺序容器:如 vector, deque, list,按顺序存储元素。
      • 关联容器:如 set, map, unordered_set, unordered_map,按特定顺序存储元素。
      • 适配器容器:如 stack, queue, priority_queue,为其他容器提供特定功能。
    • 算法(Algorithms):用于操作容器的数据,如排序、查找、修改等,常见的算法有 sort, find, reverse 等。
    • 迭代器(Iterators):用于访问容器中的元素,可以通过迭代器来遍历容器。迭代器类似于指针。
    • 函数对象(Function Objects):通过重载 operator() 实现的可调用对象,常用于 STL 算法中,如 std::greater, std::less

37. 定义内联函数。C++ 中能有递归的内联函数吗?

内联函数是通过 inline 关键字声明的函数,它的目的是减少函数调用时的开销。内联函数会在调用时将函数体直接插入到调用点,而不是进行常规的函数调用。这能减少函数调用的性能开销,尤其适合一些简单且频繁调用的函数。

递归的内联函数:
递归函数通常不能作为内联函数,因为递归调用需要多次执行,编译器无法预知每次递归的调用情况,因此不能提前将其展开为内联代码。尽管可以声明递归函数为 inline,但编译器通常不会对其进行内联优化。

inline int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);  // 递归调用
}

尽管递归函数可以声明为内联,但编译器通常会拒绝对其进行内联处理,因为递归的调用结构复杂且不确定。

38. 抽象类是什么?何时使用?

抽象类是一个不能实例化的类,它包含至少一个纯虚函数。抽象类用于提供一个统一的接口,但不提供具体实现,通常用作基类。

39. 静态数据成员和静态成员函数是什么?

静态数据成员是属于类的成员,而不是对象的成员,它在程序开始时初始化并在所有对象之间共享。静态成员函数可以访问类的静态成员。

40. volatile 关键字的主要用途是什么?

volatile 关键字用于告诉编译器该变量可能会随时改变,防止编译器优化该变量,通常用于与硬件或信号处理程序交互时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MobiCetus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值