0

0

c++中如何实现深度拷贝数组_c++ std::copy与memcpy用法区别【详解】

冰火之心

冰火之心

发布时间:2026-01-22 13:15:09

|

453人浏览过

|

来源于php中文网

原创

std::copy适合对象数组的深度拷贝,memcpy仅适用于POD类型;前者调用拷贝构造或赋值运算符,后者为字节级复制,对非POD类型行为未定义。

c++中如何实现深度拷贝数组_c++ std::copy与memcpy用法区别【详解】

std::copy 适合对象数组的深度拷贝,memcpy 只能用于 POD 类型

直接结论:std::copy 会调用元素的拷贝构造函数或赋值运算符,能正确处理含指针、string、vector 等成员的对象;memcpy字节级内存复制,对非 POD(Plain Old Data)类型行为未定义——比如复制一个含 std::string 成员的 struct,memcpy 会导致两个对象共享同一块堆内存,析构时 double-free。

什么时候必须用 std::copy 而不能用 memcpy

以下情况 memcpy 会出错,必须用 std::copy

  • 数组元素是类类型且定义了非平凡拷贝构造函数(例如含 std::stringstd::vector、自定义析构逻辑)
  • 目标数组和源数组类型不同但可隐式转换std::copy 支持类型转换,memcpy 不支持)
  • 使用自定义分配器或需要触发迭代器相关语义(如 std::copy 可配合 std::back_inserter
struct Person {
    std::string name;
    int age;
};
Person src[2] = {{"Alice", 30}, {"Bob", 25}};
Person dst[2];
// ✅ 正确:调用 string 的拷贝构造
std::copy(src, src + 2, dst);
// ❌ 危险:name 内部指针被位移复制,析构时崩溃
memcpy(dst, src, sizeof(Person) * 2);

memcpy 在什么场景下比 std::copy 更快且安全

memcpy 仅在满足所有下列条件时可安全替代 std::copy,且通常有性能优势(编译器可能内联为 SIMD 指令):

  • 元素类型是 POD:无用户定义构造/析构/赋值函数,无虚函数,无非静态引用成员
  • 源与目标内存不重叠(否则应改用 memmove
  • 你知道确切字节数,且地址对齐(现代编译器通常自动优化对齐访问)
// ✅ 安全且高效:int 是 POD,连续内存
int src[] = {1, 2, 3, 4};
int dst[4];
memcpy(dst, src, sizeof(int) * 4); // 比 std::copy 略快,尤其大数据量

std::copy 的常见误用与陷阱

即使类型安全,std::copy 也容易因迭代器错误导致越界或静默失败:

MCP Market
MCP Market

MCP Servers集合平台,帮你找到最好的MCP服务器

下载

立即学习C++免费学习笔记(深入)”;

  • 目标空间不足:不会检查目标容量,写越界是未定义行为
  • 反向复制误用正向迭代器:std::copy 不自动适配 std::reverse_iterator,需显式用 std::copy_backward
  • 传入空指针或非法迭代器(如 end() 作为起始)不报错,但行为未定义
  • std::vector 使用原生指针时,若 vector realloc 导致迭代器失效,后续 copy 可能崩溃

建议始终搭配 std::vector::data() 或范围检查:

std::vector src = {1, 2, 3};
std::vector dst(src.size());
std::copy(src.begin(), src.end(), dst.begin()); // 安全:size 匹配

真正麻烦的不是选哪个函数,而是没想清楚「这个类型到底算不算 POD」——C++20 起可以用 std::is_trivially_copyable_v 编译期断言,但很多老项目连 都没引入。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1490

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

229

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

86

2025.10.17

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

100

2025.10.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

393

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

573

2023.08.10

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.8万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.6万人学习

Django 教程
Django 教程

共28课时 | 3.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号