或者这没关系吗?
我正在学习C并掌握结构。我试图模仿一个基本的";构造函数";方法,方法是将字符串值传递给一个方法,创建一个新的结构对象,然后从函数中返回。我已经意识到有几种允许的方法:
- 直接创建一个结构对象,而无需卸载到方法
- 声明我的结构对象的所有成员变量,然后将其传递给"构造函数"方法
- 将要填充对象的值直接传递到"构造函数"方法中,并将结果存储在结构对象中
- 在一行中使用我的"constructor"方法创建和使用结构对象,而不存储它
这是我的代码,你会明白我的意思:
#include <stdio.h>
#include <string.h>
struct Book {
char title[50];
char author[50];
int pageCount;
};
void printBook(struct Book _book) {
printf("%s by %s is %d pages long.n", _book.title, _book.author, _book.pageCount);
}
struct Book createBook(char *title, char *author, int pageCount) {
struct Book newBook;
strcpy(newBook.title, title);
strcpy(newBook.author, author);
newBook.pageCount = pageCount;
return newBook;
}
int main() {
// 1. Create a struct object directly.
struct Book hp1;
strcpy(hp1.title, "Harry Potter and the Philosopher's Stone");
strcpy(hp1.author, "J. K. Rowling");
hp1.pageCount = 223;
printBook(hp1);
// 2. Declare the member variables, then pass to a 'constructor' method.
char t2[] = "A Game of Thrones";
char a2[] = "George R. R. Martin";
int pc2 = 687;
struct Book got1 = createBook(t2, a2, pc2);
printBook(got1);
// 3. Directly pass the member data to the 'constructor' method.
struct Book ag = createBook("American Gods", "Neil Gaiman", 465);
printBook(ag);
// 4. Create a new object instance without storing it.
printBook(createBook("Coraline", "Neil Gaiman", 186));
return 0;
}
我的问题是,这些不同方法的优点和缺点是什么?我知道,如果你想重用对象,方法4显然是不明智的,但它适合一次性使用吗?将字符串值传递给函数而不先将其存储在变量中(方法3(是否存在任何隐藏成本,或者这总是比先存储它(方法2(更具性能?
您应该注意,如果您传递的字符串长度超过50字节,此函数将导致未定义的行为。
在这种情况下,应该使用strncpy
,并确保0-byte
位于数组的末尾。
struct Book createBook(char *title, char *author, int pageCount)
{
struct Book newBook;
strncpy(newBook.title, title, sizeof(title));
strncpy(newBook.author, author, sizeof(author));
newBook.title[49] = 0; // Truncate the string if it was too long
newBook.author[49] = 0;
newBook.pageCount = pageCount;
return newBook;
}
情况1并不是真正的";构造函数";因为你只需在需要的地方初始化它。
情况2是浪费堆栈空间,因为您在堆栈上创建了一个数据副本,然后将其传递到堆栈上创建另一个副本,并将其传递回堆栈,这也将在堆栈上生成一个副本。之后,您的结构中已经有了值,所以我会引用那些不再需要的变量的insead。
案例3+4基本相同,是最好的方法。如果您不再需要本地对象,只是为了调用方法,那么就不需要保留副本。
不过,您应该意识到,尤其是对于较大的结构,按值复制对象是非常无效的,因此您可能必须考虑动态分配对象,并在完成后释放它。由于C
不像C++
那样提供析构函数机制,所以您必须自己做。
您实现";构造函数";不过不需要任何解除分配。