在C++中移动语义是否缺少C?

ozg*_*gur 3 c c++ move c++11

我一直在SO和其他来源上搜索此事,但我无法解决这个问题.使用rvalues和xvalues的资源对C++来说有点新(使用C++ 11).

现在,我们 - C程序员 - 错过了什么吗?或者C中有相应的技术可以从这些资源效率中受益?

编辑:这个问题不是基于意见.我无法描述我的问题.我要问的是c中是否有相应的技术.

AnT*_*AnT 9

当然,在C中也有类似的技术.我们已经在C中做了"移动语义"多年.

首先,C++中的"移动语义"基于一系列重载决策规则,这些规则描述了在重载决策期间rvalue引用参数的函数如何表现.由于C不支持函数重载,因此这个特定问题不适用于C.您仍然可以通过使用专用名称编写专用数据移动函数并在要移动数据时显式调用它们来手动实现C语言中的移动语义.复制它.例如,对于您自己的数据类型,struct HeavyStruct您可以使用适当的实现编写a copy_heavy_struct(dst, src)move_heavy_struct(dst, src)函数.在每种情况下,您只需手动选择最合适/最有效的呼叫.

其次,C++中隐式移动语义的主要目的是在深度复制不必要地低效的上下文中作为隐式深层复制语义的替代.由于C没有隐式深拷贝语义,因此在C中甚至不会出现问题.C总是执行浅复制,这已经非常类似于移动语义.基本上,您可以将C视为一种始终移动的语言.它只需要一些手动调整就可以使其移动语义达到完美.

当然,从字面上重现C++移动语义的所有特征可能是不可能的,因为,例如,不可能将C指针绑定到rvalue.但几乎所有东西都可以"模仿".它只需要明确/手动完成更多工作.

  • @ sp2danny:嗯......这是浅层和深层复制的非正统定义.在我的书中*浅拷贝*是复制,只复制对象的直接成员,对象的顶级内存(正是原始`memcpy`所做的那样),但间接忽略对象拥有的任何内存(通过指针或引用) .*深度复制*是复制,它复制对象的每个部分,而不管为了到达该部分,必须通过多少级别的间接.如果一个对象可以被一个`memcpy`正确复制,那么该对象是平的,不需要深度复制. (7认同)
  • 虽然我同意有人可以说对于一个平面对象(不需要深复制)浅复制与深复制*等效*。因此,如果您愿意,可以将其称为深复制,只是不要坚持认为这也不能称为浅复制。 (2认同)

Mat*_*son 5

我不相信 C 缺少移动语义。这是导致移动语义在 C 中“缺失”的所有 C++ 功能。由于您无法执行调用函数来分配内存的自动结构复制,因此您没有自动复制复杂且昂贵的数据结构的系统。

当然,这是本意。C 是一种比 C++ 更轻量级的语言,因此创建自定义复制和赋值构造函数的复杂性并不意味着成为语言的一部分 - 您只需编写代码来完成需要作为函数完成的工作。如果你想要“深拷贝”,那么你会写一些东西来遍历你的数据结构并分配内存等。如果你想要浅拷贝,你会写一些东西来将数据结构中的指针复制到另一个(并且可能设置源到NULL) - 就像移动语义构造函数一样。

当然,您只需要 C 中的 L 和 R 值(它在 = 符号的左侧或右侧),没有引用,并且显然没有 R 值引用。这是在 C 中通过使用(将事物转换为指针)的地址来实现的。

因此,C 缺少的并不是真正的移动语义,而是 C++ 语言设计附带的复杂构造函数和赋值运算符(等)使移动语义在该语言中成为有用的东西。像往常一样,语言会根据它们的特性发展。如果您没有特征 A,而特征 B 依赖于特征 A 的存在,那么您就不需要“需要”特征 B。

当然,除了异常处理和常量引用[以及 C++11 中的 R 值引用,本质上是一个允许修改的常量引用],我认为 C++ 中没有任何主要特性可以不是通过 C 实现的。它有时会有点笨拙和混乱(并且在语法上不会那么漂亮,并且当您以错误的方式覆盖函数时,编译器不会给您整洁的错误消息,您需要手动强制转换指针等)。[在陈述这样的事情之后,有人会指出“你显然没有想到X”,但总体来说仍然是正确的——C可以做你想用C做的99.9%]