如何理解Move参数中的const Source和var Dest

C++ std::move 移动语义:从值类别到性能优化的核心机制 在 C++ 编程中,资源管理和性能优化是核心议题。传统深拷贝在处理大型对象(如容器、字符串)时开销巨大,影响程序效率。移动语义(Move Semantics)的引入正是为了解决这一问题,它通过资源所有权的转移而非复制来提升性能。其原理基于 C++11 对值类别的细化,将表达式分为左值、纯右值和将亡值(xvalue)。std::move 本质上是一个类型转换器,它将左值无条件转换为将亡值,从而为移动构造函数和移动赋值运算符的调用创造条件。这项技术的核心价值在于实现高效、零开销的资源转移,广泛应用于标准库容器( 阅读详情
如何理解Move参数中的const Source和var Dest

总结作者:SkyJacker
贡献者:小峰,LiuXiao
http://www.cnpack.org
CnPack IV  QQ Group: 130970
2007-01-31
(转贴请注明作者、出处且保持完整)

Q:
procedure Move(const Source; var Dest; Count: Integer);
问一下这里的参数Source和Dest没有说明数据类型,那具体应该如何使用啊?

var
  xx, yy: array [0..6] of Char;
begin
  FillChar(xx, 7, #0);
  xx := 'abcdef';
  Move(xx, yy, 4);
  Move(xx[0], yy[0], 4)
  //上面这两条语句有什么区别
end;  

A:

xx, yy就是一块数据。
xx[0] 就是这块数据的第一个字符
这两个的起始地址相同,因此move的结果也相同了。  

测试代码:
procedure TForm1.btnXClick(Sender: TObject);
var
  xx, yy: array [0..6] of Char; // 内容存在栈里
  a: array of Char; // 内容存在堆里,这就可以理解为什么动态数组a代表的是字符串的指针了
begin
  SetLength(a, 10);
  FillChar(xx, 7, #0);
  xx := 'abcdef';
  a[0]:='A';
  a[1]:='B';
  Move(xx, yy, 4);
  Move(xx[0], yy[0], 4);
  Move(xx,a[0],4);
end;  

顺便再解释一下 Move 的 Pascal 源码(Windows XP Sp2 Delphi6 + Update2 ):

procedure Move( const Source; var Dest; count : Integer );
{$IFDEF PUREPASCAL}
var
  S, D: PChar;
  I: Integer;
begin
  S := PChar(@Source);
  D := PChar(@Dest);
  if S = D then Exit;
  if Cardinal(D) > Cardinal(S) then //精华1:小心,别覆盖了Source
    for I := count-1 downto 0 do
      D[I] := S[I]
  else
    for I := 0 to count-1 do
      D[I] := S[I];
end;

{$ELSE}
asm
{     ->EAX     Pointer to source       }
{       EDX     Pointer to destination  }
{       ECX     Count                   }

        PUSH    ESI
        PUSH    EDI

        MOV     ESI,EAX
        MOV     EDI,EDX

        MOV     EAX,ECX

        CMP     EDI,ESI
        JA      @@down
        JE      @@exit

        SAR     ECX,2           { copy count DIV 4 dwords       }
        JS      @@exit

        REP     MOVSD

        MOV     ECX,EAX         //精华2: 放之四海皆准。
        AND     ECX,03H        
        REP     MOVSB           { copy count MOD 4 bytes        }
        JMP     @@exit

@@down:
        LEA     ESI,[ESI+ECX-4] { point ESI to last dword of source     }
        LEA     EDI,[EDI+ECX-4] { point EDI to last dword of dest       }

        SAR     ECX,2           { copy count DIV 4 dwords       }
        JS      @@exit
        STD
        REP     MOVSD

        MOV     ECX,EAX        
        AND     ECX,03H         { copy count MOD 4 bytes        }
        ADD     ESI,4-1         { point to last byte of rest    }
        ADD     EDI,4-1
        REP     MOVSB
        CLD
@@exit:
        POP     EDI
        POP     ESI
end;
{$ENDIF}

注:

C/Pascal等高级语言里头的指针其实是一个存储了地址的内存单元,其存储的内容(是一个地址)所指的地方才是这个指针所指的内容。
而I:Integer只是一个内存单元,I的内容是整型变量,@I才能得到I的地址。

Pascal中的无类型变量,相当于C中的void。参数const Source; var Dest; 可以理解为两块内存区域。这两参数调用时在汇编中的实现,便是将Source和Dest的“地址值”作为参数传入,而并非传入这两变量本身。

但在函数内部的Pascal实现中,Source是传入的地址再指了一次而得到的结果,因此仍然代表传进来之前的Source。欲取得汇编中实现时传入来的地址,则需要用@Source。也就是说,这个var封装并且隐藏了函数被调用时传入的取地址操作和函数体内部使用时指了一次的操作。

 
C++11 移动语义陷阱:5个常见错误与std::move的正确使用 本文深入探讨C++11移动语义的常见陷阱,包括std::move误用、移动构造与拷贝构造混淆等问题,并提供5个典型错误场景的解决方案。通过代码实例和最佳实践,帮助开发者避免资源管理错误,提升程序性能与安全性。 阅读详情

相关推荐

C++移动语义与完美转发:从值类别到高效编程实践

在C++编程中,资源管理和参数传递是影响性能的关键因素。理解值类别(左值、右值、将亡值)和引用类型是掌握现代C++的基础,它们定义了对象的身份和可移动性。基于这一原理,C++11引入了移动语义,通过资源所有权转移而非复制来提升效率,其核心是移动构造函数和移动赋值运算符的实现。这一技术价值在于大幅减少了动态内存、文件句柄等资源管理的开销。在应用场景上,移动语义广泛应用于标准库容器操作、工厂函数和返回值优化。而完美转发则解决了泛型编程中参数传递的痛点,通过通用引用和引用折叠规则,配合std::forward保持

weixin_34326179的博客 386

C++11 自定义Move构造函数(Move Constructor)和Move赋值运算符(Move Assignment Operators)

在C++11的标准当中,引入了右值的概念以及跟右值密切相关的Move语义,由此C++的类定义中也多了2个成员函数:Move构造函数和Move赋值运算符。这篇文章将讨论如何为我们自己的类编写Move 构造函数和Move赋值运算符。 class IntArray 是一个Int 类型的数组,它的类定义如下: #pragma once #include <iostream> #inclu...

姜的理想国 6775

C++移动语义误用详解:五大典型场景与避坑指南

移动语义是现代C++中用于优化资源管理、提升程序性能的核心机制,其本质是所有权的转移而非资源的简单复制。理解其底层原理对于编写高效、安全的代码至关重要,尤其在涉及动态内存、文件句柄等昂贵资源管理时,正确的移动操作能显著减少深拷贝开销。然而,误用移动语义可能导致数据损坏、悬空指针等难以调试的问题,严重影响软件稳定性与可维护性。本文聚焦于移动语义在实际工程中的应用陷阱,通过剖析返回局部变量、通用引用转发、移动后使用源对象等高频误用场景,结合C++11/14/17标准特性,提供系统的避坑指南与最佳实践,帮助开发者

weixin_33994429的博客 381

移动一个const对象会发生什么?

我们知道,通过移动操作从一个对象中“窃取”数据的时候,被窃取的那个对象会被修改。这也是为什么移动构造函数要声明成Test(Test&&)的原因。当我们对一个const对象进行移动时,直觉上可能会认为,无法编译通过。毕竟移动操作会修改源对象,但是原对象又是一个const对象,很矛盾。但是实际上上面的代码可以编译通过。但是最好不要对const对象应用移动操作,如果这个对象尺寸很大的话,拷贝操作的代价很高。可见,如果试图对一个const对象进行移动操作,最终会使用拷贝来作为一个变通方法。

tianyingang的博客 720

西门子PLC填充块指令FILL_BLK与UFILL_BLK应用详解

在工业自动化编程中,内存操作是影响程序效率和稳定性的核心技术。理解连续数据块的高效管理原理,对于优化PLC程序性能至关重要。通过块操作指令,工程师可以实现批量数据初始化、缓冲区管理等功能,显著提升代码执行效率。在西门子TIA Portal环境中,FILL_BLK和UFILL_BLK指令正是实现这一技术价值的关键工具,广泛应用于设备初始化、上位机通讯数据准备等场景。特别是在处理DB块地址操作和优化访问机制时,这两个指令的选择与正确使用直接关系到程序的可靠性。本文深入解析这两个指令的差异,帮助工程师掌握数据块填

weixin_34007020的博客 416

【C++11保姆级教程】移动构造函数(move constructor)和移动赋值操作符(move assignment operator)

在C++11标准中引入了移动语义的概念,通过移动构造函数和移动赋值操作符,我们可以更高效地管理对象的资源。本文将以通俗易懂的方式详细解释移动构造函数和移动赋值操作符的概念,并通过生动的比喻帮助读者更好地理解这两个概念。当我们需要在C++中处理大量数据或动态分配的对象时,移动构造函数和移动赋值操作符成为了重要的工具。它们是C++11引入的特性,旨在提高程序的性能和效率。

m0_62599305的博客 1万+

std::move一个const对象

类型,这意味着移动构造函数或移动赋值操作符无法应用于这个对象,因为它们通常要修改源对象,而。本身只是将对象的类型转换为右值引用,使得可以使用移动语义。对象的结果,通常会退化到使用拷贝构造或拷贝赋值,就像没有使用。修饰符强制性地从该对象中移除来实现,方法是使用。,即便转换为右值引用,依然会被视为。的语义,可能会引发未定义的行为。对象实际上不会移动该对象。但需要注意,这样做会违反。

折花刀的博客 854

STM32实战篇:使用USART发送/接收数据

在发送字符时也可以直接使用其对应的ASCLL码,例如: USART_SendData(USART1, 0x61);

qq_74114817的博客 596

深入理解Move Constructor和Move Assignment

    之前的一篇博客讲了左值引用和右值引用,并且细致地说到了右值实际上就是“一闪而过”的结果,它是程序在计算时候的一个中间量,这个中间量如果我们能够有效的利用上,那么我们再创建对象(Constructor)的时候或是给已有对象(Assignment)赋值的时候很多资源就不用再重新申请了,直接把右值的资源“steal”过来。不要小看这一步的改变,如果你的程序频繁地创建对象,并且一个对象创建需要进行...

zhangsj1007的博客 6929

Keil5保姆级安装指南:从破解到STM32开发环境配置(附常见错误解决方案)

本文提供Keil5从安装到STM32开发环境配置的完整指南,包含破解步骤、常见错误解决方案及多芯片支持配置。详细讲解环境预检、核心安装、许可证管理及高效开发环境设置,帮助开发者快速搭建嵌入式开发平台。特别针对安装和卸载过程中的关键问题提供专业解决方案。

weixin_30369041的博客 124

别再傻傻分不清了!用Design Compiler和PrimeTime实操对比PBA与GBA模式

本文深度解析静态时序分析(STA)中Design Compiler与PrimeTime工具的PBA与GBA模式差异,通过实际案例演示两种模式在转换时间计算、时钟路径分析等方面的对比,并提供工程实践中模式选择的策略与调试技巧,帮助工程师在芯片设计流程中平衡精度与效率。

weixin_42552315的博客 415

move函数的用法

delphi中move函数的正确理解 收藏 我们能看到以下代码var pSource,pDest:PChar;     len: integer;.......................//一些代码Move(pSource,pDest,len); //错误Move(pSource^,pDest^,len); //正确看起来确实好像是传值,而不是传地址,但是各位别忘了,这不是C,C++,而是D...

weixin_33690963的博客 6436

基于GEC6818开发板+Linux+Qt设计的智能养老院出入管理系统(195)

当前,传统的养老院出入管理模式普遍存在信息更新滞后、数据统计繁琐、实时监控能力不足等问题,难以满足现代养老机构对安全管理与服务质量提升的需求。本系统设计正是针对这些问题,通过集成先进的硬件设备如高性能GEC6818开发板以及RFID刷卡模块,结合稳定高效的嵌入式Linux操作系统和QT开发框架,构建一套功能齐全、操作直观、响应迅速的智能出入管理系统。 该系统能自动记录并实时显示老人的进出时间,方便管理人员及时了解每位老人的活动轨迹,同时具备强大的后台管理功能,支持管理员便捷地进行老人信息的增删改查操作。通

1069

Day1-右值引用与移动语义:从拷贝到移动的范式革命

场景做法原因返回局部对象return obj;依赖 NRVO/隐式移动,不要加std::move返回临时对象return T{};prvalue,C++17 强制消除拷贝向容器插入右值避免拷贝,直接移动容器间转移元素当元素确定不再需要时移动构造函数标记noexcept保证 STL 容器 realloc 时选择移动移动赋值运算符包含自赋值检查防止delete[]后资源丢失在类中声明析构函数同时声明移动操作避免编译器不生成默认移动操作参数按值传递调用方决定拷贝还是移动。

如风逝去 341

GhidraMCP:AI驱动的逆向工程革命——让LLM自主操作Ghidra进行自动化分析

(Ghidra Machine Control Protocol)应运而生,它通过将LLM与Ghidra(美国NSA开源逆向工具)结合,实现了AI驱动的自动化逆向工程流程。逆向工程是软件安全、漏洞分析和代码审计的核心环节,但传统方法依赖人工分析,耗时且易出错。未来,随着LLM技术的演进和逆向工程工具的优化,GhidraMCP有望成为安全研究人员和开发者的核心工具,推动逆向工程进入“AI辅助时代”。GhidraMCP通过LLM与Ghidra的深度整合,重新定义了逆向工程的自动化边界。

这里汇聚了前沿的技术分享与实用的开发技巧,带你探索从创意到企业的技术创业之路。 2116

lammps教程:ovito免费输出高清图片方法

基本原理是调用ovito软件包中的TachyonRenderer模块,该模块可实现Tachyon渲染,达到和ovito 2.9 Tachyon完全相同的效果。这种方法在后来的ovito版本中已经不能使用,但是ovito 2.9版本在后处理方面功能较少,使用起来也不是特别方便。在之前的推文中,曾介绍过使用ovito 2.9版本更换Tachyon渲染器实现高清图片的输出。这个方法只需要配置ovito模块即可,完全免费,不需要购买ovito pro版。具体的配置参数可到ovito官网查询。大家好,我是小马老师。

lammps_jiayou的博客 2767

右值引用与移动语义:从拷贝到移动的范式革命

std::cout << "Buffer 移动赋值 from size=" << size_ << "\n";std::cout << "Buffer 移动构造 from size=" << size_ << "\n";

如风逝去 367

硬件工程师的破局之路:为何你才是考取软考高级架构师的“天选之子”?

硬件工程师如何转型系统架构师:独特优势与实战路径 文章揭示了硬件工程师在考取系统架构设计师证书时的独特优势。作者指出,硬件工程师的全局思维、接口设计能力和可靠性经验正是系统架构的核心要素。通过将硬件经验升维为架构思维(从引脚到接口、从单板到系统、从实现到权衡),硬件背景反而成为竞争优势。文章建议通过知识补全、建立架构决策日志和术语转换练习来备考,并强调硬件工程师在软硬协同时代的独特价值——既能统领硬件设计,又能为软件搭建最佳舞台。文末鼓励硬件工程师以更高视野看待职业发展,将系统架构师认证视为水到渠成的职业升

云轩阁 534

BabelDOC:如何把外文 PDF 论文变成双语对照版

BabelDOC 是一个命令行运行的 PDF 论文翻译与双语对比工具:它解析英文论文的排版、文本与公式,调用 OpenAI 兼容模型生成中文译文,再输出保留原排版的双语 PDF。适合需要大量阅读外文文献的科研读者,以及想把翻译能力集成进自己程序的开发者。 ## 📌 它解决的现实痛点 [![BabelDOC 双语对照排版效果预览,左英文原文右中文翻译](https://raw.gitcode.

gitblog_00865的博客 497

4、LTE无人机认证:保障通信安全的新方案

本文针对LTE网络中无人机通信存在的安全风险,提出了一种基于可信第三方GCS的新型认证协议。该协议通过非对称加密和哈希函数保护IMSI等敏感信息,防止身份泄露、中间人攻击、拒绝服务攻击和位置追踪等威胁。利用Scyther工具对协议进行形式化分析,验证了其在机密性、一致性和活性等方面的安全属性,证明该方案能有效提升无人机在LTE网络中的通信安全性与隐私保护能力。

pink的博客 61

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++11右值引用与移动语义:高性能编程的核心机制

在C++编程中,对象拷贝是常见的性能瓶颈,尤其是在处理容器、字符串或自定义资源管理类时,深拷贝会带来显著的开销。为了解决这一问题,C++11引入了右值引用和移动语义,它们通过识别临时对象(右值)并转移其资源,避免了不必要的复制。这一机制不仅提升了标准库容器(如std::vector和std::string)的性能,还为自定义类的资源管理提供了高效方案。移动语义的核心在于移动构造函数和移动赋值运算符,它们允许将即将销毁的对象的资源“窃取”过来,从而减少内存分配和拷贝操作。在实际应用中,结合完美转发和noexc

weixin_30381317的博客 500

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Python命令行工具开发:argparse模块从入门到实战

命令行接口(CLI)是程序与用户交互的重要方式,它允许用户通过终端输入参数来控制程序行为。其核心原理在于解析命令行参数,将用户输入转换为程序可处理的数据结构。在Python生态中,标准库的argparse模块提供了声明式配置的解决方案,能自动完成参数解析、验证、类型转换和帮助文档生成,极大提升了脚本的健壮性和可维护性。这一技术价值在于让开发者能够快速构建专业、用户友好的命令行工具,降低使用门槛。无论是数据处理、自动化脚本还是项目脚手架,都需要处理复杂的参数输入场景。通过掌握argparse的位置参数、可选参

weixin_30416871的博客 345

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深入解析C++ STL迭代器:从核心概念到工程实践

迭代器是泛型编程中的核心抽象概念,它提供了一种统一访问容器元素的方式,屏蔽了底层数据结构的差异。其工作原理是通过定义一组通用的操作接口(如递增、解引用),使得算法能够独立于具体容器实现。这一机制的技术价值在于实现了数据结构和算法的高效解耦,极大地提升了代码的复用性和泛化能力。在应用场景上,迭代器不仅是C++ STL(标准模板库)的基石,连接着容器与算法,也是实现如**迭代器适配器**(如反向迭代器、插入迭代器)和**迭代器萃取**机制的关键,后者使得算法能在编译期根据迭代器能力选择最优实现。理解迭代器的分类

diaoqu4574的博客 363

C++泛型编程实战:从模板基础到STL应用与元编程

泛型编程是编写不依赖具体数据类型的代码范式,其核心原理是通过模板实现编译期多态,从而提升代码复用性和类型安全性。这一技术价值在于能够构建高度抽象且性能优异的可复用组件,广泛应用于高性能计算库、游戏引擎和通用框架开发。在C++中,模板机制包括函数模板、类模板和变参模板,配合STL容器与算法,形成了标准化的泛型实践体系。本文聚焦C++实战,通过解析模板特化、SFINAE等高级技巧,并结合STL的迭代器与算法设计,深入探讨如何规避代码膨胀、优化编译错误,并引入C++20概念约束以提升接口清晰度,为开发者提供从基础

weixin_34259232的博客 419

C++字符序列:从内存编码到std::string与string_view高效实践

字符序列是编程中处理文本数据的基础概念,涉及内存中字节的组织与解释。其核心原理在于通过特定编码规则(如ASCII、UTF-8)将字符映射为二进制数据,并在内存中连续存储。理解这一原理对实现高效、安全的文本处理至关重要,直接关系到程序的内存安全与性能。在C++工程实践中,字符序列的技术价值通过多种工具体现:C风格字符串提供底层控制但易出错;std::string通过自动内存管理(包括**短字符串优化SSO**)提升了开发效率与安全性;而C++17引入的**std::string_view**则实现了零成本的只

weixin_30432579的博客 642

C++指针深度解析:从内存模型到智能指针的实战指南

指针是计算机编程中用于直接操作内存地址的核心概念,它本质上是一个存储内存地址的变量。理解指针需要从计算机内存模型入手,内存被组织为线性字节序列,每个字节拥有唯一地址,变量则是具名内存区域。指针通过存储地址实现了对数据的间接访问,这一机制带来了动态内存管理、高效函数参数传递、硬件直接访问等关键技术价值,广泛应用于操作系统、数据库、游戏引擎等高性能场景。在C++中,指针语法涉及声明、取地址(&)、解引用(*)等操作,同时需警惕野指针、内存泄漏等常见问题。现代C++通过智能指针(如unique_ptr、share

cuiyingchan0663的博客 395
上一篇: 如何获取多核、多cpu系统中指定cpu的序列号
下一篇: 关于函数调用中形参的分析
skyjacker
博客等级 码龄23年 11粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值