从函数返回对象的最佳方法是什么(C)

a52*_*a52 2 c struct pointers

这在某种程度上是一个主观问题,但似乎应该有一个标准.我正在制作树状数据结构,我想知道从函数传递新节点的最佳方法.我有几个想法,但我不知道哪个是最安全/最有效的.

这是我的代码的简化:

typedef struct Node {
    struct Node *left;
    struct Node *right;
    int value;
} Node;

int f() {
    //do stuff
}

Node *new_node() {
    Node n = {NULL, NULL, f()};
    return &n;
}

int main() {
    Node a = {new_node(), new_node(), 0};
}
Run Code Online (Sandbox Code Playgroud)

显然,这不起作用,因为new_node()函数返回的指针指向堆栈分配的数据,一旦new_node()结束就会释放.但是解决这个问题的最佳方法是什么?

一种可能性是n在堆上分配,如下所示:

Node *new_node() {
    Node *n = (Node *) malloc(sizeof(Node)); //unsure if the cast is necessary here, but that's not relevant
    n->left = NULL;
    n->right = NULL;
    n->value = f();
    return n;
}
Run Code Online (Sandbox Code Playgroud)

但这感觉不对,因为它要求调用者函数直接处理内存清除,这可能会很快变得混乱.

我见过的另一个选项(特别是当对象是数组或缓冲区而不是对象时)是传递指向函数的指针,只是修改指针的内容.

void new_node(Node *n) {
    n->left = NULL;
    n->right = NULL;
    n->value = f();
}

int main() {
    Node n = {NULL, NULL, 0};
    Node n1 = n;
    new_node(&n);
    new_node(&n1);
    Node a = {&n, &n1, 0};
}
Run Code Online (Sandbox Code Playgroud)

或者你可以直接传递数据,特别是因为Node在这种情况下这么小:

 Node new_node() {
     Node n = {NULL, NULL, f()}
     return n;
 }
Run Code Online (Sandbox Code Playgroud)

这似乎会慢一点,虽然我不确定.

关于这个主题已经有了一些答案,但它们都是用C++编写的,并且处理引用和指针,我恐怕我并不真正理解它们之间的区别.

这样做的标准方法是什么?

(对不起,如果这太长了)

das*_*ght 5

您涵盖了所有四种可用方法,包括一种无效方法.在他们之间挑选取决于您的设计偏好:

  • 您正确地指出第一种方法已被破坏
  • 第二种方法适用于您创建的对象无法静态分配的情况,例如,因为直到运行时才知道您需要多少个对象
  • 第三种方法适用于初始化静态分配的对象,因为它不需要复制,它可以让您避免手动资源管理
  • 由于希望避免复制,最后一种方法不太常见.这几乎普遍等于过早优化,因此这种方法也是完全有效的.

  • 我知道这是不恰当的评论使用,但祝贺达到500K! (3认同)