C++中使用memcpy的拷贝问题

文章目录

目录

文章目录

前言

一、memcpy的作用

[二、memcpy 在 C++ 里的 4 大致命问题](#二、memcpy 在 C++ 里的 4 大致命问题)

[1. 不能拷贝带有 指针 / 引用 / 动态内存 的对象](#1. 不能拷贝带有 指针 / 引用 / 动态内存 的对象)

例子1:

例子2:

[2. 不调用拷贝构造函数 / 赋值运算符](#2. 不调用拷贝构造函数 / 赋值运算符)

[3. 对象有虚函数时,memcpy 会直接破坏虚表指针](#3. 对象有虚函数时,memcpy 会直接破坏虚表指针)

[三、什么情况可以用 memcpy?](#三、什么情况可以用 memcpy?)


前言

推荐学完虚函数这章再回来看,不然有些概念理解不了


提示:以下是本篇文章正文内容

一、memcpy的作用

原型:

cpp 复制代码
void* memcpy(void* dest, const void* src, size_t n);

作用 :把 src 开始的 n 个字节 ,无脑逐字节复制 到 dest

特点 :只拷贝内存,不调用任何构造函数、析构函数、赋值运算符

定位: memcpy是典型的浅拷贝

二、memcpy 在 C++ 里的 4 大致命问题

1. 不能拷贝带有 指针 / 引用 / 动态内存 的对象

例子1:

cpp 复制代码
class string {
    char* data; // 动态分配内存
};

string a = "hello";
string b;
memcpy(&b, &a, sizeof(a)); // ❌ 大错特错

结果:

a 和 b 指向同一块内存

析构时 重复释放同一块内存 → 程序崩溃

例子2:

cpp 复制代码
int main()
{
bite::vector<bite::string> v;
v.push_back("1111");
v.push_back("2222");
v.push_back("3333");
return 0;
}

问题分析:

  1. memcpy 是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存
    空间中
  2. 如果拷贝的是自定义类型的元素, memcpy 既高效又不会出错,但如果拷贝的是自定义类型
    元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为 memcpy 的拷贝实际是浅
    拷贝

由于扩容后,需要将原来的数据拷贝到新开辟的空间上,使用了memcpy后,💜紫色空间的的数据拷贝到💙蓝色空间,因此两个_str都指向了同一个空间"1111"

开辟新空间后,自然要释放旧空间,可是旧空间和新空间都指向同一块地址,因此释放完旧空间,新空间里的_str指向的内容就丢失了


2. 不调用拷贝构造函数 / 赋值运算符

C++ 对象的拷贝必须走自己的拷贝逻辑,而 memcpy 完全跳过:

不调用拷贝构造,不调用 operator=,不处理资源,不维护类内部状态


3. 对象有虚函数时,memcpy 会直接破坏虚表指针

cpp 复制代码
#include <iostream>
#include <cstring> // memcpy
using namespace std;

class Base {
public:
    virtual void show() {
        cout << "Base::show()" << endl;
    }
    virtual ~Base() = default;
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived::show()" << endl;
    }
};

int main() {
    Derived d;   // 真实类型 Derived
    Base     b;  // 真实类型 Base

    // 重点:用 memcpy 暴力拷贝对象内存
    memcpy(&b, &d, sizeof(Base));

    // 现在 b 的虚表指针已经被篡改成 Derived 的虚表指针了!
    b.show();  // 这里会出现诡异行为:要么乱输出,要么直接崩
}

b 本来是 Base 类型,有自己的虚表指针 vptr, memcpy 把 d 的全部内存 拷给 b,包括它的 vptr

结果:b 的对象本体是 Base,虚表指针却是 Derived 的

这就叫对象切片 + 虚表错乱 ,C++ 标准里叫未定义行为(UB)


三、什么情况可以用 memcpy?

  1. 纯数据类型(int、float、结构体无指针)
  2. 无动态内存
  3. 无虚函数
  4. 无构造 / 析构逻辑
  5. 指针数组
cpp 复制代码
Base* a[2] = {new Derived, new Derived};
Base* b[2];
memcpy(b, a, sizeof(a));  // ✅ 没问题

因为只复制地址,不碰对象本身

相关推荐
一晌小贪欢10 分钟前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
xiaoye-duck42 分钟前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
一条大祥脚1 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·1 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
FRing032 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
旖旎夜光2 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
starzy19902 小时前
深入理解Scala嵌套函数:作用域封装之道
开发语言·scala
Sakura_j_h_2 小时前
从零写一个 MCP stdio Server:用 Python 校验博客文章格式
开发语言·python·自动化·ai工具·mcp·json-rpc
青少儿编程课堂4 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青4 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树