很简单的东西 看了时间长用不到就容易忘 但面试总归要问些什么
怎么办 那就再看一遍


二、C++对C语言增强的地方
C++语言完全兼容C语言,并且在C语言的基础上,扩充了一些语法,从而更方便进行软件开发。
命名空间
引用
重载
函数重载
运算符重载
面向对象特性
封装
继承
多态
泛型编程
异常处理
标准模板库STL










C++多文件命名空间完整实现
按照题目要求分为4个文件:space.h(命名空间声明)、a.cpp(加法calc实现)、b.cpp(减法calc实现)、main.cpp(调用测试)
1. space.h 头文件(命名空间函数声明)
cpp
#ifndef SPACE_H
#define SPACE_H
// 命名空间A_Space 函数声明
namespace A_Space
{
int calc(int a, int b);
}
// 命名空间B_Space 函数声明
namespace B_Space
{
int calc(int a, int b);
}
#endif
说明:头文件保护宏防止重复包含,仅做函数声明,不写实现
2. a.cpp(A_Space加法实现)
cpp
#include "space.h"
namespace A_Space
{
// 加法运算
int calc(int a, int b)
{
return a + b;
}
}
3. b.cpp(B_Space减法实现)
cpp
#include "space.h"
namespace B_Space
{
// 减法运算
int calc(int a, int b)
{
return a - b;
}
}
4. main.cpp(调用两个命名空间函数)
cpp
#include <iostream>
#include "space.h"
using namespace std;
int main()
{
int x = 10, y = 3;
// 方式1:完整域名访问(推荐,无命名冲突)
int add_res = A_Space::calc(x, y);
int sub_res = B_Space::calc(x, y);
cout << "A_Space加法结果:" << add_res << endl;
cout << "B_Space减法结果:" << sub_res << endl;
return 0;
}
编译运行指令(g++)
bash
g++ main.cpp a.cpp b.cpp -o calc_demo
./calc_demo
输出结果
A_Space加法结果:13
B_Space减法结果:7
核心知识点说明 💡
- 命名空间作用 :解决同名函数
calc冲突,不同命名空间下的同名函数相互隔离 - 头文件与源文件分离 :
.h:仅放函数/类声明 ,供外部文件#include调用.cpp:包含对应头文件,实现命名空间内函数逻辑
- 访问命名空间成员 :
命名空间名::函数名(参数),不建议同时using namespace A_Space; using namespace B_Space;,会造成calc歧义编译报错




四、对指针和数组的引用(C/C++ 完整知识点讲解)
一、基础概念区分
1. 数组本质
数组名是数组首元素的常量指针,不可被重新赋值;数组在内存中是一段连续同类型内存空间。
c
int arr[5] = {1,2,3,4,5};
// arr == &arr[0],代表首元素地址
2. 指针本质
指针是存储内存地址的变量,可自由修改指向,能指向数组、普通变量、堆内存。
c
int* p = arr; // 指针p指向数组首元素
3. 引用本质(C++独有)
引用是变量的别名 ,必须在定义时初始化,不能为空、不能改指向;分为普通变量引用、指针引用、数组引用三类。
二、数组的引用(核心语法)
1. 定长数组引用语法
格式:类型 (&引用名)[数组长度] = 数组名;
cpp
int arr[5] = {10,20,30,40,50};
// 给长度为5的int数组起别名ref_arr
int (&ref_arr)[5] = arr;
ref_arr[0] = 99; // 修改引用等价修改原数组
限制:引用数组时必须显式写明数组长度,长度不匹配会编译报错。
2. 模板适配任意长度数组引用(通用写法)
cpp
template<typename T, size_t N>
void printArr(T (&arr)[N]){
for(size_t i=0; i<N; i++){
cout << arr[i] << " ";
}
}
// 调用:自动推导数组长度
int a[3] = {1,2,3};
printArr(a);
三、指针的引用(指针别名)
语法:类型* (&指针引用名) = 原指针;
cpp
int num = 100;
int* p = #
// p_ref是指针p的别名
int* (&p_ref) = p;
*p_ref = 200; // 等价于*p=200,修改num的值
int b = 20;
p_ref = &b; // 等价p=&b,修改原指针的指向
易错区分
int &* p:非法语法,不存在指向引用的指针int* & p:合法,指针的引用(别名)
四、指针、数组、引用三者访问等价关系
对数组 int arr[5]、指针 int* p=arr、数组引用 int (&ref)[5]=arr:
以下写法完全等价:
cpp
arr[2] == *(arr + 2)
p[2] == *(p + 2)
ref[2] == *(ref + 2)
内存访问原理:地址偏移 sizeof(int) * 下标
五、完整演示代码(可直接运行)
cpp
#include <iostream>
using namespace std;
// 模板函数:接收任意长度数组引用
template<typename T, size_t N>
void show(T (&arr)[N]){
for(int i=0; i<N; i++) cout << arr[i] << " ";
cout << endl;
}
int main(){
// 1. 数组引用演示
int arr[4] = {1,3,5,7};
int (&ref_arr)[4] = arr;
ref_arr[1] = 99;
cout << "数组引用修改后:";
show(arr);
// 2. 指针引用演示
int val = 10;
int* p = &val;
int* (&ref_p) = p;
*ref_p = 999;
cout << "指针引用修改变量:" << val << endl;
// 3. 指针指向数组 + 指针引用
int* p_arr = arr;
int* (&rp) = p_arr;
cout << "指针引用访问数组:" << rp[2] << endl;
return 0;
}
输出结果
数组引用修改后:1 99 5 7
指针引用修改变量:999
指针引用访问数组:5
六、常见易错点 💡
- 数组引用长度必须匹配
int arr[3]; int (&r)[4]=arr;直接编译失败。 - 数组名是常量指针,不能赋值
arr = p;非法;但数组引用ref_arr可读写元素,仅不能修改数组首地址。 - 引用不能悬空、不能二次绑定
定义时必须绑定变量,绑定后无法更换绑定对象。 - C语言无引用语法,引用仅C++支持。
- 区分:
- 数组指针:
int (*p)[5]→ 指向整个数组的指针 - 数组引用:
int (&r)[5]→ 数组的别名
- 数组指针:
C++引用作为函数参数、返回值完整讲解
五、引用作为函数参数
1. 语法格式
cpp
void func(int &ref) {
ref = 100; // ref是实参的别名,直接操作原变量
}
int main() {
int a = 10;
func(a); // 传变量本身,不需要取地址&
// 执行后 a = 100
return 0;
}
2. 核心特点
- 操作原变量,无拷贝
引用是变量别名,函数内对引用的修改会直接作用于外部实参,不需要指针解引用,语法更简洁。 - 省去值拷贝开销
传递自定义类、大数组时,相比值传递不会复制完整对象,大幅提升性能。 - 必须传入可修改左值
- 不能传入常量、表达式、临时值:
func(5)/func(a+1)编译报错; - 若仅只读不修改,推荐使用const引用 :
void func(const int &ref),此时可传常量、临时值。
- 不能传入常量、表达式、临时值:
3. 对比三种传参方式
| 传参方式 | 拷贝对象 | 能否修改原值 | 传临时常量 | 语法复杂度 |
|---|---|---|---|---|
| 值传递 | 完整拷贝 | 不能 | 支持 | 简单 |
| 指针传递 | 拷贝地址 | 能(需*解引用) | 不支持字面量 | 繁琐(&/*) |
| 普通引用 | 无拷贝 | 能 | 不支持 | 简洁 |
| const引用 | 无拷贝 | 不能 | 支持 | 推荐只读场景 |
4. 典型使用场景
- 需要在函数内修改外部变量(替代指针);
- 传递大型自定义结构体/类,避免拷贝损耗;
- 函数只读参数,使用
const &兼顾性能与通用性。
六、引用作为函数返回值
1. 基础语法
cpp
int g_num = 10;
// 返回全局变量的引用
int& getNum() {
return g_num;
}
int main() {
int& r = getNum();
r = 99; // 直接修改全局g_num
// 链式调用:getNum() = 200; 合法
return 0;
}
2. 核心规则(⚠️ 高危禁忌)
禁止返回局部变量引用
局部变量存储在栈,函数执行完毕后栈内存释放,返回的引用会指向已销毁内存,产生野引用、未定义行为:
cpp
// 错误示例!
int& badFunc() {
int temp = 10; // 局部栈变量
return temp;
}
合法返回对象
- 全局变量 / 静态局部变量(生命周期贯穿程序);
- 传入函数的引用参数(原变量生命周期更长);
- 类成员函数返回自身
*this(实现运算符重载链式调用)。
3. 核心优势
-
支持链式运算
最经典应用:operator<<、operator=重载cppclass Test { public: int val; Test& operator=(const Test &t) { val = t.val; return *this; // 返回自身引用,支持 a=b=c } }; -
无拷贝开销
返回对象时不会生成临时副本,性能优于值返回。
4. const引用返回
若不需要外部修改返回对象,加const保护:
cpp
const int& getVal() {
return g_num;
}
// 此时 getVal() = 100; 编译报错,禁止修改
5. 典型场景
- 运算符重载(赋值、流运算符链式调用);
- 容器类返回内部元素读写引用(
vector::operator[]); - 需要函数调用表达式作为左值赋值。
两者核心总结对比
| 维度 | 引用作函数参数 | 引用作函数返回值 |
|---|---|---|
| 核心作用 | 减少拷贝、修改外部变量 | 支持左值赋值、链式调用、减少返回拷贝 |
| 生命周期风险 | 无风险(外部变量一定存活) | 高风险,严禁返回局部栈变量 |
| const修饰作用 | 允许传入临时常量,禁止修改 | 禁止外部通过返回值修改对象 |
| 经典案例 | 交换函数void swap(int &a,int &b) |
赋值运算符重载、数组下标[] |
💡开发建议
- 只读参数一律用
const &,兼顾性能与兼容性; - 输出型参数优先引用,比指针代码更简洁安全;
- 返回引用时严格校验返回对象生命周期,杜绝局部变量引用;
- 类设计中返回成员引用时,按需加
const区分读写接口。


my_swap 两种实现:指针版 + 引用版(C++)
一、引用实现(对应"引用作为函数参数"知识点)
原理
引用是变量别名,函数内直接操作原变量,无需取地址、解引用,代码简洁。
cpp
#include <iostream>
using namespace std;
// 引用作参数
void my_swap_ref(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int x = 10, y = 20;
cout << "交换前:x=" << x << " y=" << y << endl;
my_swap_ref(x, y); // 直接传变量,不用&
cout << "交换后:x=" << x << " y=" << y << endl;
return 0;
}
二、指针实现(C/C++通用)
原理
传入变量地址,函数内通过指针解引用修改原始内存数据。
cpp
#include <iostream>
using namespace std;
// 指针作参数
void my_swap_ptr(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x = 10, y = 20;
cout << "交换前:x=" << x << " y=" << y << endl;
my_swap_ptr(&x, &y); // 传变量地址,必须加&
cout << "交换后:x=" << x << " y=" << y << endl;
return 0;
}
三、完整合并代码(同时演示两种写法)
cpp
#include <iostream>
using namespace std;
// 1. 引用版交换
void my_swap_ref(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
// 2. 指针版交换
void my_swap_ptr(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
int main()
{
int num1 = 5, num2 = 8;
cout << "===== 引用交换测试 =====" << endl;
cout << "交换前:" << num1 << " " << num2 << endl;
my_swap_ref(num1, num2);
cout << "交换后:" << num1 << " " << num2 << endl;
// 重置数值
num1 = 5; num2 = 8;
cout << "\n===== 指针交换测试 =====" << endl;
cout << "交换前:" << num1 << " " << num2 << endl;
my_swap_ptr(&num1, &num2);
cout << "交换后:" << num1 << " " << num2 << endl;
return 0;
}
四、输出结果
===== 引用交换测试 =====
交换前:5 8
交换后:8 5
===== 指针交换测试 =====
交换前:5 8
交换后:8 5
五、两者核心区别对比
| 对比项 | 引用实现 my_swap_ref | 指针实现 my_swap_ptr |
|---|---|---|
| 函数形参 | int &a 引用 |
int *a 指针 |
| 调用传参 | 直接传变量 my_swap_ref(x,y) |
取地址传参 my_swap_ptr(&x,&y) |
| 内部操作 | 直接使用 a、b |
需要解引用 *a、*b |
| 空值风险 | 无引用空值,更安全 | 可能传入空指针 nullptr,会崩溃 |
| 适用语言 | 仅C++支持 | C、C++通用 |
💡关键知识点
- 如果只写
void swap(int a,int b)(值传递),函数内只是拷贝副本,无法修改外部变量,交换失效; - 引用本质是指针的语法糖,底层实现和指针类似,但对外语法更简单安全;
- 引用参数必须绑定合法左值,不能传数字常量、表达式。
C++ 左值(lvalue)、右值(rvalue)完整讲解(C++11及以后标准)
一、最简单一句话区分
能取地址 & 的是左值;不能取地址、用完就销毁的临时数据是右值。
赋值规则:等号左边只能放左值,不能放纯右值。
1. 左值 lvalue(locator value,有内存位置的值)
核心特征
- 拥有持久内存地址 ,可以用
&取地址; - 生命周期长,不会表达式结束立刻销毁;
- 可以出现在赋值运算符
=的左边; - 分为可修改左值 、const左值。
常见左值例子
cpp
int a = 10;
int arr[5] = {1,2,3};
int &ref = a;
const int b = 20;
a; // 变量a,左值
arr[0]; // 数组元素,左值
ref; // 引用,左值
b; // const常量,const左值(不能修改,但仍是左值,可&b)
函数返回左值引用也是左值:
cpp
int g = 100;
int& getG() { return g; }
getG() = 200; // 合法,返回左值,可以赋值
const左值特点
能取地址,但不能修改:
cpp
const int c = 5;
&c; // 合法
c = 10; // 报错,const左值不可修改
2. 右值 rvalue(没有持久内存,临时值)
C++11 把右值细分为两类:纯右值 prvalue + 将亡值 xvalue
2.1 纯右值 prvalue(pure rvalue,传统意义上的右值)
特征
- 临时对象、字面量,无稳定内存地址,不能
&取地址; - 表达式执行完直接销毁;
- 不能放在
=左侧。
纯右值例子
cpp
10; // 数字字面量
3 + 5; // 运算临时结果
std::string("hello"); // 临时字符串对象
int func() { return 1; }
func(); // 返回普通值,纯右值
错误示范:
cpp
10 = a; // 编译报错,纯右值不能赋值
&(3+5); // 报错,不能取纯右值地址
2.2 将亡值 xvalue(expiring value,即将销毁的对象)
C++11 新增,属于右值的一种,代表可以被移动的临时对象
产生场景
std::move(左值)转换后的结果;- 返回右值引用
T&&的函数调用。
cpp
int num = 10;
std::move(num); // xvalue 将亡值
int&& getR() {
return std::move(num);
}
getR(); // xvalue
特点:
- 属于右值,但底层拥有资源,可以移动语义(避免拷贝);
- 同样不能放在等号左边。
3. C++ 值分类整体层级(标准定义)
表达式的值类别
├─ 左值 lvalue
│ └─ const lvalue
└─ 右值 rvalue
├─ 纯右值 prvalue(字面量、普通函数返回值)
└─ 将亡值 xvalue(move转换、T&&返回)
4. 引用绑定规则(重点,区分左值引用/右值引用)
1)普通左值引用 T&
只能绑定左值,不能绑定右值
cpp
int a = 10;
int &r1 = a; // OK,绑定左值
int &r2 = 10; // 报错,不能绑定纯右值
int &r3 = std::move(a); // 报错,不能绑定xvalue
2)const左值引用 const T&
万能引用,左值、纯右值、将亡值全都能绑定
cpp
const int &r1 = a;
const int &r2 = 10;
const int &r3 = std::move(a);
函数参数常用它接收任意值,避免拷贝。
3)右值引用 T&&
只能绑定右值(prvalue / xvalue),不能绑定普通左值
cpp
int &&r1 = 10; // OK 纯右值
int &&r2 = std::move(a); // OK 将亡值
int &&r3 = a; // 报错,不能绑定左值
作用:实现移动构造、移动赋值,减少内存拷贝开销。
5. 通俗记忆总结
- 左值 = 有名字、有地址、能长期存在的变量/引用
变量、数组元素、左值引用、const变量都是左值; - 纯右值 = 无名临时数据
数字、字符串字面量、算术运算结果、返回值为普通类型的函数; - 将亡值 = 被move包装后的左值
属于右值,专门用来触发移动语义; - 赋值左边只能放可修改左值,所有右值都不能赋值;
- 取地址
&只能作用于左值,右值取地址编译报错。
6. 综合示例代码
cpp
#include <utility>
#include <string>
using namespace std;
int val = 10;
int& getL() { return val; }
int&& getX() { return move(val); }
int main() {
// 左值
val;
getL();
const int c = 5;
c;
// 纯右值
123;
1 + 2;
string("test");
// 将亡值(xvalue,右值)
move(val);
getX();
// 赋值测试
getL() = 999; // OK 左值可赋值
// 123 = 10; 报错
// move(val) = 20; 报错,右值不可赋值
return 0;
}
int g = 100;
int& getG() { return g; }
getG() = 200; // 合法,返回左值,可以赋值
getG() = 200; 这一步会得到什么结果
运行结果分步拆解
cpp
int g = 100;
int& getG() { return g; }
getG() = 200;
1. 核心原理
getG() 返回 int& 左值引用 ,等价于直接返回变量 g 本身的别名。
getG() 就等同于 g。
2. 执行过程
- 调用
getG(),函数内部return g,返回g的左值引用; - 赋值语句
getG() = 200等价于g = 200; - 全局变量
g的值被修改。
3. 最终结果
变量 g 的值从 100 变成 200。
完整验证代码
cpp
#include <iostream>
using namespace std;
int g = 100;
int& getG() {
return g;
}
int main() {
cout << g << endl; // 输出 100
getG() = 200;
cout << g << endl; // 输出 200
return 0;
}
延伸对比(反例:返回普通int)
如果函数返回值是 int(纯右值),就不能赋值:
cpp
int getG2() { return g; }
getG2() = 300; // 编译报错,纯右值不能放在赋值左侧










二、面试常问问题



C++ 完整实现代码(满足全部需求)
需求梳理
- 分配函数:通过参数带出堆内存首地址(C++ 可用指针引用
unsigned char*&,比二级指针更简洁) - 写入函数:填充 0x00、0x11、0x22 ... 0x99 共10字节
- 打印函数:控制台输出所有字节十六进制
- 堆内存使用完毕释放,防止内存泄漏
cpp
#include <iostream>
// new/delete 无需额外头文件,iostream已包含基础内存操作
// 1. 内存分配函数:使用指针引用带出堆内存首地址
void allocMemory(unsigned char*& buf, int bufSize)
{
// 在堆区分配 bufSize 字节空间
buf = new unsigned char[bufSize];
if (buf == nullptr)
{
std::cerr << "堆内存分配失败!" << std::endl;
exit(1);
}
}
// 2. 数据写入函数:填充 0x00, 0x11, 0x22 ... 0x99
void writeBuffer(unsigned char* buf, int bufSize)
{
for (int i = 0; i < bufSize; i++)
{
buf[i] = static_cast<unsigned char>(i * 0x11);
}
}
// 3. 数据输出函数:循环打印每个字节的十六进制
void printBuffer(const unsigned char* buf, int bufSize)
{
std::cout << "缓冲区字节数据:";
for (int i = 0; i < bufSize; i++)
{
// 按两位十六进制输出,不足补0
printf("0x%02X ", buf[i]);
}
std::cout << std::endl;
}
int main()
{
const int BUF_LEN = 10;
unsigned char* pBuffer = nullptr;
// 分配10字节堆内存,pBuffer通过函数参数被赋值
allocMemory(pBuffer, BUF_LEN);
// 写入指定数据
writeBuffer(pBuffer, BUF_LEN);
// 屏幕输出
printBuffer(pBuffer, BUF_LEN);
// 释放堆内存
delete[] pBuffer;
pBuffer = nullptr;
return 0;
}
运行输出结果
缓冲区字节数据:0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99
关键知识点说明
1. 分配函数 unsigned char*& buf
unsigned char*&:指针的左值引用 ,相当于C语言二级指针unsigned char**,但C++语法更优雅- 函数内修改
buf会直接改变外部实参pBuffer,实现「通过参数带回首地址」要求
2. 堆内存分配与释放
- C++ 使用
new[]分配数组堆内存,对应释放必须用delete[] - 分配后主动置空
nullptr,避免野指针
3. 数据填充逻辑
buf[i] = i * 0x11
i=0 → 0x00,i=1→0x11 ... i=9→0x99,完美匹配题目要求
4. 输出格式化
%02X:保证十六进制固定两位,例如数值 0x05 会打印 0x05 而非 0x5,格式统一
兼容C风格二级指针版本(可选,如果你习惯C写法)
cpp
void allocMemory(unsigned char** buf, int bufSize)
{
*buf = new unsigned char[bufSize];
if (*buf == nullptr)
{
std::cerr << "分配失败" << std::endl;
exit(1);
}
}
// main中调用:allocMemory(&pBuffer, BUF_LEN);



cpp
#include <iostream>
#include "as.h"
using namespace std;
int main(int argc, const char *argv[])
{
int result;
result = add(10,20);//addii
cout << "add(10,20) = " << result << endl;
result = sub(10,20);//subii
cout << "sub(10,20) = " << result << endl;
return 0;
}


任务完整实现(Linux GCC)
任务目标
- 用C语言编写动态库,自定义实现
strcpy、strcat - C++代码调用该C动态库函数(必须使用
extern "C"解决C/C++符号兼容) - 分三步:库源码→编译动态库→C++测试程序
一、C动态库源码
1. 头文件 mystring.h
c
#ifndef MYSTRING_H
#define MYSTRING_H
// 自定义strcpy:字符串拷贝
char* my_strcpy(char* dest, const char* src);
// 自定义strcat:字符串拼接
char* my_strcat(char* dest, const char* src);
#endif
2. 库实现文件 mystring.c
c
#include "mystring.h"
char* my_strcpy(char* dest, const char* src)
{
char* p = dest;
while (*src != '\0')
{
*p = *src;
p++;
src++;
}
*p = '\0'; // 追加字符串结束符
return dest;
}
char* my_strcat(char* dest, const char* src)
{
char* p = dest;
// 先走到dest字符串末尾
while (*p != '\0')
p++;
// 再拷贝src到dest尾部
while (*src != '\0')
{
*p = *src;
p++;
src++;
}
*p = '\0';
return dest;
}
二、编译生成Linux动态库(libmystring.so)
执行终端命令:
bash
# 1. 生成位置无关目标文件
gcc -c -fPIC mystring.c -o mystring.o
# 2. 链接生成动态共享库
gcc -shared mystring.o -o libmystring.so
输出文件:libmystring.so(Linux标准动态库)
三、C++测试程序 main.cpp
核心要点:extern "C" 包裹C库函数声明,关闭C++名字改编,保证能找到C库符号
cpp
#include <iostream>
#include <cstring>
using namespace std;
// 关键:extern "C" 让C++以C符号规则链接动态库函数
extern "C"
{
char* my_strcpy(char* dest, const char* src);
char* my_strcat(char* dest, const char* src);
}
int main()
{
char buf[128] = {0};
// 测试strcpy
my_strcpy(buf, "Hello ");
cout << "拷贝结果:" << buf << endl;
// 测试strcat拼接
my_strcat(buf, "Dynamic Library");
cout << "拼接结果:" << buf << endl;
return 0;
}
编译C++程序并链接动态库
bash
# 编译:指定动态库路径 -L. ,链接库 -lmystring
g++ main.cpp -o test_demo -L. -lmystring
运行程序(临时加载当前目录动态库)
bash
# Linux需要指定动态库搜索路径
export LD_LIBRARY_PATH=.
./test_demo
运行输出
拷贝结果:Hello
拼接结果:Hello Dynamic Library
四、关键知识点说明 💡
-fPIC:生成位置无关代码,动态库必须加该参数,支持内存地址重定向-shared:GCC生成共享动态库的参数extern "C"- C++默认会对函数名做名字改编(name mangling),C动态库是纯C符号,二者不匹配会报
undefined reference - 用
extern "C"包裹声明,强制使用C风格符号名,实现C++调用C库
- C++默认会对函数名做名字改编(name mangling),C动态库是纯C符号,二者不匹配会报
- 动态库链接参数
-L.:告诉编译器在当前目录寻找库文件-lmystring:链接libmystring.so,lib前缀与.so后缀自动省略
LD_LIBRARY_PATH:Linux运行时动态库搜索环境变量,程序启动时去该路径加载.so
Windows平台补充(MinGW编译)
生成dll动态库命令
bash
gcc -c -fPIC mystring.c
gcc -shared mystring.o -o libmystring.dll
C++编译运行
bash
g++ main.cpp -o test.exe -L. -lmystring
# 运行时将libmystring.dll和test.exe放同一目录
./test.exe