直接返回结构或填充指针?

时间:2018-04-17 13:26:44

标签: c

假设我有以下函数来初始化数据结构:

void init_data(struct data *d) {
        d->x = 5;
        d->y = 10;
}

但是,使用以下代码:

struct data init_data(void) {
        struct data d = { 5, 10 };
        return d;
}

这不会因为复制省略而被优化掉,并且与前一版本一样高效吗?

我尝试在godbolt上进行一些测试以查看程序集是否相同,但在使用任何优化标记时,所有内容总是完全优化掉,没有任何内容,但是这样的内容:movabsq $42949672965, %rax ,我不确定在实际代码中是否会发生同样的情况。

我提供的第一个版本在C库中似乎很常见,我不明白为什么它们应该和RVO一样快,后者需要更少的代码。

1 个答案:

答案 0 :(得分:0)

  

我提供的第一个版本似乎在C库中很常见,我不明白为什么它们应该同样快速   RVO,后者需要较少的代码。

首次如此普遍的主要原因是历史性的。从文字初始化结构的第二种方式不是标准的(好吧,它只是static初始值设定项,而不是自动变量)并且它永远不允许在任务中使用(嗯,我是' ve没有检查最近标准的状态)甚至,在古代C中,一个简单的任务为:

 struct A a, b;

 ...

 a = b;  /* this was not allowed a long time ago */

根本没被接受。

因此,为了能够在每个平台上编译代码,您必须编写旧方法,正常情况下,现代编译器允许您编译遗留代码,而相反(旧编译器接受新代码)是不可能的

这也适用于返回结构或按值传递它们。除了通常是资源的巨大浪费(看到整个结构被复制到堆栈中或复制回适当的地方,一旦函数返回,这很常见)旧的编译器不接受这些,所以为了便携,你必须避免使用这些结构。

最后一条评论:不要使用你的编译器来检查两个构造是否生成相同的代码,可能它会...但你会得到错误的假设,这是常见的,而你&# 39; ll遇到错误。另一种不同的实现可以(并且允许)进行不同的翻译并产生不同的代码。