📜  常见的C++面试问题|套装2(1)

📅  最后修改于: 2023-12-03 15:09:46.332000             🧑  作者: Mango

常见的C++面试问题|套装2

C++是面向对象的编程语言,广泛应用于自动化、网站、游戏、系统编程等领域。下面是常见的C++面试问题。

C++中如何取绝对值?

在C++中,可以使用abs()函数取整数的绝对值,使用fabs()函数取浮点数的绝对值。例如:

#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
int main() {
  int i = -5;
  double d = -3.14;
  cout << abs(i) << endl; // 输出 5
  cout << fabs(d) << endl; // 输出 3.14
  return 0;
}
C++中如何调用父类的构造函数和成员函数?

在C++中,可以使用初始化列表来调用父类的构造函数,格式为Derived::Derived(argument_list) : Base(argument_list) {...}。在子类中,可以使用Base::function()来调用父类的成员函数。例如:

#include <iostream>
using namespace std;
class Base {
public:
  Base(int val) {
    num = val;
  }
  void display() {
    cout << "num = " << num << endl;
  }
private:
  int num;
};
class Derived : public Base {
public:
  Derived(int val1, int val2) : Base(val1) {
    num2 = val2;
  }
  void show() {
    display();
    cout << "num2 = " << num2 << endl;
  }
private:
  int num2;
};
int main() {
  Derived d(10, 20);
  d.show();
  return 0;
}
C++中如何设计线程池?

线程池可以提高系统的并发能力,通常包含以下几个部分:

  1. 任务队列:存储等待执行的任务。
  2. 线程池管理器:控制线程池的创建、销毁、扩容、缩减等操作。
  3. 工作线程:执行任务。

下面是一个简单的线程池实现:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
class ThreadPool {
public:
  ThreadPool(size_t threads) {
    for (size_t i = 0; i < threads; i++) {
      workers.emplace_back([this] {
        for (;;) {
          function<void()> task;
          {
            unique_lock<mutex> lock{tasks_mutex};
            condition.wait(lock, [this] { return stop || !tasks.empty(); });
            if (stop && tasks.empty())
              return;
            task = move(tasks.front());
            tasks.pop();
          }
          task();
        }
      });
    }
  }
  ~ThreadPool() {
    {
      unique_lock<mutex> lock{tasks_mutex};
      stop = true;
    }
    condition.notify_all();
    for (auto &worker : workers)
      worker.join();
  }
  template <typename T>
  auto enqueue(T task) -> future<decltype(task())> {
    auto wrapper = make_shared<packaged_task<decltype(task())()>>(move(task));
    {
      unique_lock<mutex> lock{tasks_mutex};
      tasks.emplace([=] { (*wrapper)(); });
    }
    condition.notify_one();
    return wrapper->get_future();
  }
private:
  vector<thread> workers;
  queue<function<void()>> tasks;
  mutex tasks_mutex;
  condition_variable condition;
  bool stop = false;
};
int main() {
  ThreadPool pool(4);
  vector<future<int>> results;
  for (int i = 0; i < 8; i++) {
    results.emplace_back(
      pool.enqueue([i] {
        cout << "hello " << i << endl;
        this_thread::sleep_for(chrono::seconds(1));
        cout << "world " << i << endl;
        return i * i;
      })
    );
  }
  for (auto && result : results)
    cout << result.get() << ' ';
  cout << endl;
  return 0;
}
C++中智能指针的作用是什么?

在C++中,智能指针是一种自动管理资源的指针,可以避免内存泄漏和野指针的问题。C++标准库提供了两种智能指针:unique_ptrshared_ptr

unique_ptr是一个独占式的智能指针,用于管理资源的所有权。它的特点是只能由一个unique_ptr拥有,在拥有它的unique_ptr释放资源之后,其它unique_ptr都将失效。例如:

#include <iostream>
#include <memory>
using namespace std;
int main() {
  unique_ptr<int> ptr(new int(10));
  cout << *ptr << endl; // 输出 10
  unique_ptr<int> ptr2(move(ptr));
  cout << (ptr == nullptr) << endl; // 输出 1
  cout << *ptr2 << endl; // 输出 10
  return 0;
}

shared_ptr是一个共享式的智能指针,用于管理资源的引用计数。它的特点是可以由多个shared_ptr共享一个对象,在最后一个shared_ptr释放资源之后才会释放。例如:

#include <iostream>
#include <memory>
using namespace std;
class A {
public:
  A() {
    cout << "A()" << endl;
  }
  ~A() {
    cout << "~A()" << endl;
  }
  void display() {
    cout << "hello" << endl;
  }
};
int main() {
  shared_ptr<A> ptr1(new A());
  shared_ptr<A> ptr2 = ptr1;
  ptr1->display(); // 输出 hello
  ptr2->display(); // 输出 hello
  return 0;
}
C++中如何实现堆排序?

堆排序是一种高效的排序算法,可以在O(NlogN)的时间复杂度内完成排序。实现堆排序通常需要用到最大堆或最小堆。

在最大堆中,父节点的值大于等于子节点的值,根节点的值最大。在最小堆中,父节点的值小于等于子节点的值,根节点的值最小。

下面是使用最大堆实现堆排序的代码:

#include <iostream>
#include <vector>
using namespace std;
void max_heapify(vector<int>& nums, int i, int n) {
  int left = 2 * i + 1;
  int right = 2 * i + 2;
  int largest = i;
  if (left < n && nums[left] > nums[largest]) {
    largest = left;
  }
  if (right < n && nums[right] > nums[largest]) {
    largest = right;
  }
  if (largest != i) {
    swap(nums[i], nums[largest]);
    max_heapify(nums, largest, n);
  }
}
void build_max_heap(vector<int>& nums) {
  for (int i = nums.size() / 2 - 1; i >= 0; i--) {
    max_heapify(nums, i, nums.size());
  }
}
void heap_sort(vector<int>& nums) {
  build_max_heap(nums);
  for (int i = nums.size() - 1; i >= 1; i--) {
    swap(nums[0], nums[i]);
    max_heapify(nums, 0, i);
  }
}
int main() {
  vector<int> nums{4, 9, 7, 2, 6, 5, 1, 3, 8};
  heap_sort(nums);
  for (auto num : nums) {
    cout << num << ' ';
  }
  cout << endl;
  return 0;
}