AI部署通用C++知识点–面试必知必会(part1)

whdahanh 发布于 2025-09-29 222 次阅读


1. #include:双引号 " " vs. 尖括号 < >

结论先行

  • 项目内头文件:优先用 "..."
  • 系统/已安装第三方库头文件:用 <...>

查找顺序(通用思路)

  • #include "名字"
    1. 先在“当前包含该语句的文件所在目录”查找
    2. 再查 用户指定的包含目录(如编译器的 -I/“Additional Include Directories”)
    3. 最后查 系统包含目录(标准库、系统 SDK 等)
  • #include <名字>
    1. (部分编译器也会查用户指定包含目录)
    2. 直接查 系统包含目录

一句话经验:项目内用 "...",系统或第三方库(已安装到系统路径)用 <...>


2. 指针、常量指针、指针常量;const 的价值

2.1 指针的本质

  • 指针是“带类型的地址变量”:
    • :保存一块内存的地址
    • 类型:知道自己“指向什么类型”
    • 解引用:通过 *p 访问该地址处的对象

2.2 “常量指针” vs “指针常量”

  • 常量指针(pointer to const)const int *p;    // 等价于 int const *p;
    int x = 10, y = 20;
    const int *p = &x;
    p = &y;   // ✅ 可以改指向
    *p = 30;  // ❌ 不可改值
    • 记忆const 靠近 *p,约束“所指之物”。
    • 含义:不能通过 p 修改所指向的值;但 p 自身可改指向
  • 指针常量(const pointer)int *const p = &x;
    int x = 10, y = 20;
    int *const p = &x;
    *p = 30;  // ✅ 可改值
    p = &y;   // ❌ 指针本身不可变
    • 记忆const 靠近标识符 p,约束“指针自身”。
    • 含义p 本身的地址 不可变;但 可改所指向的值
  • 两者皆定const int *const p = &x; // 值与指针均不可变

2.3 const 的优势

  • 防误改:语义化“只读”。
  • 接口更清晰void printStr(const char* s); // 承诺不修改来访数据
  • 利于优化/更安全
    • 编译期常量折叠、更少可变性带来更好推断
    • 与 #define 相比:const有类型、有作用域,可调试
  • 编译期常量作为数组大小(需可在编译期确定):const int N = 10;
    int a[N]; // ✅ 若 N 的值编译期可知

3. C++11 新特性速览

3.1 统一初始化(Initializer List)

int arr[3]{1,2,3};
std::vector<int> v{1,2,3,4};
struct Point { int x; int y; };
Point p{10,20};
  • 避免缩窄(narrowing),更安全:
double d = 3.14;
int x(d);    // 允许(可能截断)
int y = d;   // 允许(可能截断)
int z{d};    // ❌ 编译错误:从 double 到 int 的缩窄

3.2 auto 类型推导

  • 由 初始化表达式 推导类型:
auto x = 10;                 // int
auto it = v.begin();         // std::vector<int>::iterator
  • 约束要点:
    • 必须初始化auto a; ❌)
    • 不能作 函数形参类型
    • 不能直接定义 数组类型auto arr[] = ... ❌;auto p = "abc"; 是指针)
    • 同一声明语句里各变量推导类型必须一致
  • 与 decltype 配合,模板代码更简洁。

3.3 decltype 表达式求型

int a = 5;
decltype(a) b = 10; // b 为 int

规则速记

  1. exp 非括号包围的名字/表达式 → 推导为其 类型本身
  2. exp 是函数调用 → 推导为 返回类型
  3. exp 为 左值 或 被括号包围 → 推导为 引用类型

示例:

class Base { public: int m; };
int fun(int a, int b){ return a + b; }

int x = 2;
decltype(x) y = x;                // int
decltype(fun(x,y)) sum = 0;       // int(fun 的返回类型)

Base A;
decltype(A.m) u = 0;              // int
decltype((A.m)) r = u;            // int&  —— 注意括号

decltype(x+y) c = 0;              // int
decltype(x = x + y) d = c;        // int&  —— 左值

与 auto 的差别

  • auto:由 初始值 推导,必须初始化,更简洁
  • decltype:由 任意表达式 推导,不必初始化,更灵活

3.4 范围 for(Range-based for)

std::vector<int> v{1,2,3};
for (auto &x : v) {
    x *= 2;
}
  • 可读性强,不再显式使用迭代器/下标。

3.5 nullptr

void f(int);
void f(char*);
f(nullptr); // 调用 f(char*),避免与 f(int) 二义性
  • 类型安全的空指针常量,优于 NULL/0

3.6 Lambda 表达式

语法

[capture](params) -> ret { body }

示例

auto add = [](int x, int y){ return x + y; };
std::for_each(v.begin(), v.end(), [](int &x){ x *= 2; });

捕获用法

int a = 10, b = 20;

// 按值捕获
auto by_val = [=](){ /* 读 a,b 的副本 */ };

// 按引用捕获
auto by_ref = [&](){ a *= 2; b += 5; };

3.7 智能指针(Smart Pointer)

  • 头文件:<memory>
  • std::unique_ptr:独占所有权,不可拷贝,可移动(std::move)。
  • std::shared_ptr:共享所有权,引用计数;注意循环引用问题。
  • **std::weak_ptr**:弱引用,不增加计数,用于打破循环引用,可 lock() 获得临时 shared_ptr

示例(避免循环引用):

#include <memory>
#include <iostream>

class A;class B;

class A {
public:
    std::shared_ptr<B> b;
    ~A(){ std::cout << "A destroyed\n"; }
};

class B {
public:
    std::weak_ptr<A> a; // 用 weak_ptr 观察 A
    ~B(){ std::cout << "B destroyed\n"; }
};

int main(){
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    a->b = b;
    b->a = a; // 不会形成循环引用

    if (auto locked = b->a.lock()) {
        std::cout << "lock ok\n";
    }
}

3.8 左值/右值 与 移动语义

  • 左值(lvalue):有稳定存储位置,可取地址,可做赋值号左侧;如变量、解引用结果等。
  • 右值(rvalue):临时对象/表达式结果;不可持久绑定到非常量左值引用。

移动示例

std::vector<int> v1{1,2,3};
std::vector<int> v2 = std::move(v1); // 资源转移,避免深拷贝
  • std::move(x) 只是把 x转换为右值引用(T&&),提示可移动;并不“搬运”数据。

引用类别

int a = 10; int& lr = a;  // 左值引用
int&& rr = 5 + 2;         // 右值引用

4. 速记清单(Cheat Sheet)

  • #include:项目内 "...";系统/第三方 <...>
  • const:读语义、防误改、利优化;#define 无类型且仅文本替换。
  • 指针修饰:const T* p值不可改) vs. T* const p指针不可改)。
  • 统一初始化 {}:禁止危险缩窄。
  • auto 需初始化;decltype 按表达式求型。
  • nullptr 避免重载二义性。
  • Lambda:捕获 [=](值)/[&](引用)。
  • 智能指针:优先 unique_ptr,共享用 shared_ptr,破环用 weak_ptr
  • 移动语义:std::move 表达可移动性,减少拷贝。


微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2025-09-29