通过传递引用或返回引用来初始化结构是更好的风格吗?



假设我有以下内容:

typedef struct {
    int x;
    int y;
    char a;
    char b;
} myStruct;

是更好的做法,创建一个新的myStruct与一个函数通过传递一个引用到一个空的,或通过返回一个myStruct从一个函数?

void init(myStruct* s){
    //some code
}
int main(){
    myStruct s;
    init(&s);
    return 0;
}

myStruct init(){
    myStruct r;
    //some code
    return r;
}
int main(){
    myStruct s = init();
    return 0;
}

这基本上只是惯例。第一种风格在C代码中更常见,第二种风格在c++代码中更常见。

在c++中,他们会说第二种是首选的,因为在第一种中,如果你分配了一个结构体,但忘记调用init,那么你可能会遇到一个"无头对象"被传递的混乱局面。

在c++中,init函数通常只是一个构造函数,因此不存在初始化失败的可能性。

在c++中,如果你打开优化,效率不会有任何差异,编译器会做"复制省略"并优化第二个,使其看起来与第一个相似。

这取决于您将什么视为初始状态。对一些人来说,这意味着全部为零,对另一些人来说,这意味着默认状态,或者有意义的状态。

不同的初始状态定义有不同的方法

对于归零结构体,只需执行

struct mystruc s = {0};

如果结构体需要特定的值初始化,它可能看起来像:

struct mystruc s = {1, 2, NULL, 0x1234};
对于非平凡的初始化,我个人喜欢这样:
struct mystruc s;
if ( mystruc_init(&s) < 0 ) it_is_fail();

IMO,你的第二个方法myStruct s = init();不强制初始化任何超过上述方法,程序员可能仍然做myStruct s;没有得到警告,我个人讨厌返回复杂数据类型的局部变量。

如果struct的初始化不能失败,我个人更喜欢并建议您只按值返回它,因为这是您最终想要的概念:让函数传递超出其作用域的一些值-这正是返回值的设计目的。

如果您习惯了"此数据类型需要初始化"这种习惯用法,那么您就不太可能忘记

MyStruct foo = init_myStruct();

比执行两步"声明和填充"过程要好。更容易读,更容易写。

还必须注意的是,指针传递方法不能用于初始化const限定的结构体,因此,您基本上别无选择,只能按值返回

我个人经常对简单的数据对象使用聚合初始化:

struct MyStruct {
    int x;
    int y;
    char a;
    char b;
};
int main()
{
    MyStruct s = {10, 20, 'e', 'u'};
}

硬编码默认值如下:

struct MyStruct {
    int x;
    int y;
    char a;
    char b;
};
const MyStruct MyDefault_A = {0, 0, 'a', 'z'};
const MyStruct MyDefault_B = {10, 20, 'e', 'u'};
int main()
{
    MyStruct s = MyDefault_A;
}

最新更新