5

如果我有以下情况: -

struct foo
{
  int a;
  int *b;
} bar;

void baz(struct foo qux)
{

}

我是否认为传递barbaz()会导致本地副本bar被推入堆栈?如果是这样,这是什么副本?在 C++ 中,我假设它会调用复制构造函数或默认的复制构造函数,但我真的不知道这在 C 中是如何工作的。

C 是否有任何默认复制构造函数的概念,并且它有名称吗?可以做些什么来执行深层复制吗?(假设)。我能想到的唯一方法是实际进行深层复制,然后将其传递给函数。

通常,我会传递一个指向 a 的指针,foo但我只是好奇它是如何工作的。此外,我的印象是传递指针更快,节省内存,并且是执行此类操作时推荐的操作过程。我猜这是一个浅拷贝;这可以改变吗?

4

2 回答 2

4

我是否认为将 bar 传递给 baz() 会导致 bar 的本地副本被推入堆栈?

是的。

我真的不知道这将如何在 C 中工作。

基本上与 C++ 中的默认复制构造函数一样;副本的每个字段都使用原始字段的相应字段进行初始化。当然,由于“好像”规则,整个事情可能归结为memcpy.

我的印象是传递指针更快,节省内存,并且是执行此类操作时推荐的操作过程。

对于较大struct的 s,通常是这种情况,但并非总是如此;如果您有struct少量小字段,则复制的开销可能会小于间接的开销(此外,使用指针参数可能会很昂贵,因为 C 和 C++ 的别名规则会阻止一些优化)。

我猜这是一个浅拷贝;这可以改变吗?

不,浅复制(盲目复制每个字段)是默认复制构造函数所发生的(而“深复制”通常意味着创建指针/引用字段中引用的每个对象的副本)。

你的意思是“通过引用传递”,它不是默认允许最大灵活性(以及与原始类型传递的一致性)。如果你想通过引用传递你传递一个指针(或 C++ 中的一个引用),通常const如果你只是为了性能,否则你传递对象本身。

于 2013-04-18T22:18:50.387 回答
1

是的,将 bar 的本地副本推入堆栈。其余的对以下工作示例进行评论。

    #include <stdio.h>
    struct foo
    {
        int a;
        int *b;
    } bar;
    void baz(struct foo qux)
    {
        bar.a = 2; // if its a different copy then printf on main should print 1 not 2.
        *bar.b = 5; // if its a different copy then printf on main should print 5 not 4. since the place pointer pointing to is same
    }
    int main(){
        bar.a=1;
        bar.b = (int*)malloc(sizeof(int));
        *bar.b = 4;
        baz(bar); // pass it to baz(). now the copy of bar in the stack which is what baz going to use
        printf("a:%d | b:%d\n",bar.a,*bar.b);
        //answer is  2 and 5
        /*So indeed it does a shallow copy thats why we lost the "4" stored in bar.b it did not created new space in heap to store "5" instead it used the same space that b was pointing to.
        */
    return 0;
    }
于 2013-04-18T22:34:38.590 回答