首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中的移动语义是C缺少的吗?

C++中的移动语义是C缺少的吗?
EN

Stack Overflow用户
提问于 2017-04-07 05:27:16
回答 5查看 1.9K关注 0票数 8

我一直在寻找这件事的SO和其他来源,但我不能把我的头脑围绕这个问题。使用rvalue和xvalue的资源对于C++ (使用C++11)来说有点新。

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

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-04-07 06:21:19

当然,C中也有类似的技术,我们在C中做“移动语义”已经有很长时间了。

首先,C++中的“移动语义”是基于一组重载解析规则的,这些规则描述了在过载解析过程中带有rvalue引用参数的函数的行为。由于C不支持函数重载,这一特定问题不适用于C。您仍然可以手动实现C中的迁移语义,方法是使用专用名称编写专用数据移动函数,并在希望移动数据时显式调用它们,而不是复制它们。例如,对于您自己的数据类型struct HeavyStruct,您可以使用适当的实现同时编写copy_heavy_struct(dst, src)move_heavy_struct(dst, src)函数。您只需手动选择在每种情况下调用的最合适/最有效的一个。

其次,在C++中,隐式移动语义的主要目的是在深度复制效率不高的上下文中充当隐式深拷贝语义的替代。因为C没有隐含的深拷贝语义,所以在C中甚至不会出现这个问题。C总是执行浅层复制,这已经非常类似于move语义了。基本上,你可以把C看作是一种总是移动的语言。它只是需要一些手动调整,以使其移动语义达到完美。

当然,可能无法从字面上再现C++ move语义的所有特性,例如,不可能将C指针绑定到rvalue。但实际上一切都可以被“模仿”。它只需要显式/手动地做更多的工作。

票数 15
EN

Stack Overflow用户

发布于 2017-04-07 06:41:58

我不相信C缺少的是移动语义。C中“缺少”的是导致移动语义的所有C++功能,因为您不能执行调用函数来分配内存的自动结构副本,所以您没有一个自动复制复杂而昂贵的数据结构的系统。

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

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

所以C所缺少的并不是真正的移动语义,而是随着C++语言的设计而来的复杂构造函数和赋值运算符(等等),使得移动语义在该语言中非常有用。与往常一样,语言是根据它们的特点演变的。如果你没有特征A,而特征B取决于特征A的存在,你就不需要特征B。

当然,除了异常处理和const引用以及C++11中的R值引用(这基本上是允许您修改的const引用)之外,我不认为C++中有任何主要特性不能通过C来实现(有时会有些尴尬和混乱(在语法上不会很好,编译器不会给您提供整洁的错误消息,当您以错误的方式覆盖函数时,您将需要手动转换指针等等)。在这样的陈述之后,有人会指出“你显然没有想到X",但总体说法仍然是正确的--C可以做你想用C做的99.9%的事情

票数 6
EN

Stack Overflow用户

发布于 2017-04-07 06:55:08

不是的。您必须自己滚动,但就像C++的其他特性(例如多态)一样,您可以使用更多的编码来实现相同的语义:

代码语言:javascript
复制
#include<stdlib.h>

typedef struct {
    size_t cap;
    size_t len;
    int* data;
} vector ;

int create_vector(vector *vec,size_t init_cap){
    vec->data=malloc(sizeof(int)*init_cap);
    if(vec->data==NULL){
        return 1;
    }
    vec->cap=init_cap;
    vec->len=0;
    return 0;
}

void move_vector(vector* to,vector* from){
    //This effects a move...
    to->cap=from->cap;
    to->len=from->len;
    free(to->data);
    to->data=from->data;//This is where the move explicitly takes place.

    //Can't call destroy_vec() but need to make the object 'safe' to destroy.
    from->data=NULL;
    from->cap=0;
    from->len=0;

}

void destroy_vec(vector *vec){
    free(vec->data);
    vec->data=NULL;
    vec->cap=0;
    vec->len=0;
}

注意在move_vector()data是怎样的(好的…)从一个向量移动到另一个矢量。

在对象之间传递资源的想法在C中很常见,最终等同于“移动语义”。C++刚刚正式化了它,清理了它,并将它合并到重载中。

你很可能是自己做的,却没有意识到,因为你没有名字。资源的“所有者”被更改的任何地方都可以解释为“移动语义”。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43270305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档