我是一名学习过程序员的java程序员。有一个问题归档功能。这有什么区别:
main()
{
struct person myperson;
myperson = myfunction();
return;
}
struct person myfunction()
{
struct person myPerson;
myPerson.firstname = "John";
myPerson.lastname = "Doe";
return myPerson;
}
VS
main()
{
struct person *myperson;
myperson = myfunction();
return;
}
struct person* myfunction()
{
struct person *myPerson;
myPerson = malloc(sizeof(struct person));
myPerson->firstname = "John";
myPerson->lastname = "Doe";
return myPerson;
}
这些在C中合法吗?你会选择一个而不是另一个。 非常感谢你们!
答案 0 :(得分:7)
第一个版本在堆栈上分配对象,并返回副本。第二个版本在堆上创建对象,并向其返回指针(这与Java引用最接近,但内存不会自动释放)。你不应该忘记稍后在返回的指针上调用free()
。
int main(void)
{
...
return 0;
}
我建议您阅读a good C book。这是你要问的基本内容。
答案 1 :(得分:7)
第一个代码示例:
你在堆栈的myfunction()中创建一个struct并返回它。然后,您创建另一个堆栈结构,然后复制第一个到第二个。第一个被摧毁。当你超出范围时,第二个将被自动销毁。
实际上已经创建了 2个结构。
第二个代码示例:
你在myfunction()中创建一个结构,然后只复制地址。 main中的struct实际上是相同的struct。
在这里只创建一个结构。
两个代码示例都可以工作,但是对于以后你必须显式释放为结构分配的内存,以避免内存泄漏,但性能应该更好,因为你不需要复制结构!
修改强>
如@Mat所述:这当然忽略了malloc()的开销,而小结构则不然。
答案 2 :(得分:4)
答案 3 :(得分:3)
两者都合法,都有效。
第一个版本更简单,您可以避免处理内存分配和释放。
第二个版本对更大的结构体的性能会更好,因为你可以避免将整个结构放在堆栈上以便将其移交。
答案 4 :(得分:3)
我实际上会选择第三种方式。让调用者担心提供存储空间(自动或动态分配):
void myfunction(struct person* myPerson)
{
myPerson->firstname = "John";
myPerson->lastname = "Doe";
}
可以使用自动或动态分配的变量调用该函数:
struct person autoperson;
myfunction(&person);
struct person dynamic_person = malloc(sizeof struct person);
myfunction dynamic_person);
答案 5 :(得分:1)
第一个将在堆栈上分配struct person
,并将其副本传回,然后释放原始文件。第二个将在堆上分配它并将指针传递给已分配的位置,并且不会释放它。
答案 6 :(得分:0)
第一个在堆栈上分配变量。来自myfunction的person对象从函数中复制并返回效率较低,但是你不能得到一个好的内存泄漏。
第二个示例将指针(*)返回给动态分配的person对象(使用malloc)。 malloc分配的person对象永远不会被销毁,除非你明确地调用free(),你没有 - 所以你有内存泄漏。
你需要在C中显式释放内存,它没有像Java这样的垃圾收集。
答案 7 :(得分:0)
第一个选项在堆栈上创建一个结构,当返回它时,它会被复制到main()
函数中定义的结构中。还复制了字段。对于较大的结构,这可能是一项昂贵的操作。
第二个选项分配动态内存,返回时不会被复制。您必须free()
指针以避免内存泄漏。
当然这取决于你的需求,但对于更重要和更长寿的物品,我会选择第二种选择。我还建议编写分配/初始化函数和相应的释放函数。 (见下文原因)
问题是你在myfunction()
中设置的2个字符串在函数外部是无效的,因为它们也是在堆栈上创建的。您必须使用strdup()
或类似函数才能使此失败。当然,为了不让内存泄漏,你需要free()
strdup
个指针,就像使用malloc()
一样。
答案 8 :(得分:0)
在第一个代码中,myPerson
是类型struct person
的对象,由实现本身管理(*)。在第二个代码中,它是struct person *
类型的对象(指向struct person
的指针)。在第二个代码中,对象本身必须由程序员(malloc
,realloc
,free
)管理。
此外,在第一个代码中,对象本身被复制几次,而在第二个代码中,“仅”复制指针。 通常,指针比结构类型的对象小得多。
使用第二种方法,但请记住free
对象。
更好的是,在父函数中创建对象并将指针传递给函数:sruct person *myfunction(struct person *data) { /* ... */ }
(*)我的意思是它创建和删除的时间和内容
答案 9 :(得分:0)
第一个:
main()
{
// create a person struct on the stack
struct person myperson;
// copy the struct returned by myfunction to myperson.
myperson = myfunction();
}
struct person myfunction()
{
// create a person struct on the stack.
struct person myPerson;
myPerson.firstname = "John";
myPerson.lastname = "Doe";
// return the myPerson struct. After myFunction returns, the memory
// holding the myPerson struct on the stack will be freed.
return myPerson;
}
第二个:
main()
{
// create a pointer to a person struct on the stack
struct person *myperson;
// assign the pointer returned by myfunction to myperson
myperson = myfunction();
}
struct person* myfunction()
{
// create a pointer to a person struct on the stack
struct person *myPerson;
// allocate memory for a person struct in dynamic memory and set myPerson
// to point to that memory. This memory will remain valid until it's freed by
// a call to the "free" function. Using malloc is much slower than creating
// an object on the stack. There is also the added performance cost of
// freeing the allocated memory at a later stage.
myPerson = malloc(sizeof(struct person));
myPerson->firstname = "John";
myPerson->lastname = "Doe";
// return the myPerson pointer
return myPerson;
}