结构中的默认成员值或默认构造函数参数?
Default member values or default constructor parameters in structures?
在现代 C++ 中,我可以实现具有默认成员值的结构,即
struct A
{
int x = 5;
float y = 1.0f;
};
但我也可以创建一个没有 "default member values" 但可以使用默认参数调用其构造函数的结构,如下例所示:
struct B {
int x;
float y;
B(int x_ = 5, float y_ = 1.0f) : x(x_), y(y_) {}
};
我想知道的是,从干净的代码或架构的角度来看,它们之间是否有任何区别?或者也许还有其他更重要的区别?在第一种情况下,我要编写的代码量较少,而且我相信即使未定义构造函数,我仍然可以像 A({2, 3.14f})
那样构造对象。
你会以哪种方式进入项目,为什么?
没有"right"选择初始化形式的方式,这取决于项目的具体constraints/circumstances甚至个人喜好。但是,我认为在决定 pro/contra in-class 初始值设定项时应考虑这些问题。
Pro:可读性。当您想了解 class 的用途时,您通常会从它的定义开始。在遍历数据成员时,让您的大脑在其类型旁边看到每个数据成员的初始值会很舒服,而不是扫描可能的多个构造函数。
Pro:当不需要 copy-pasting 另一个现有构造函数的初始值设定项时,添加更多构造函数会容易得多。使用 in-class 成员初始值设定项,您不太可能在添加构造函数时忘记一些初始化。
Pro:删除构造函数很容易。假设您从一个新的 class 开始,添加了一堆成员函数、一个构造函数和数据成员。然后你想起了 Scott Meyers 在 "How Non-Member Functions Improve Encapsulation" 中所说的话,你决定将成员函数变成免费的。你的类型现在看起来像一个愚蠢的 struct
与一些数据打包在一起 - 当它的构造函数不涉及任何业务逻辑时,你可能想要将类型转换为聚合:使用 in class 初始值设定项,您只需删除构造函数 - 完成。
Contra:无论何时使用 in class 初始化器,都必须知道被初始化的数据成员的具体类型。当有问题的 class 定义在 header 中(最有可能),编译时间是一个问题(最有可能),有问题的数据成员有一个 heavy-weight 时,这可能会成为问题定义(有时)and/or 需要 non-trivial 依赖于构造(有时)。一个简单的准则可能是:在 Pimpl-idiom 有用的情况下,它比第 1.-3 点更重要。并且不排除 in-class 初始值设定项,因此请使用 Pimpl。
最后说明:核心指南建议在 C.48 中使用 in-class 初始值设定项,原因是:
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
在现代 C++ 中,我可以实现具有默认成员值的结构,即
struct A
{
int x = 5;
float y = 1.0f;
};
但我也可以创建一个没有 "default member values" 但可以使用默认参数调用其构造函数的结构,如下例所示:
struct B {
int x;
float y;
B(int x_ = 5, float y_ = 1.0f) : x(x_), y(y_) {}
};
我想知道的是,从干净的代码或架构的角度来看,它们之间是否有任何区别?或者也许还有其他更重要的区别?在第一种情况下,我要编写的代码量较少,而且我相信即使未定义构造函数,我仍然可以像 A({2, 3.14f})
那样构造对象。
你会以哪种方式进入项目,为什么?
没有"right"选择初始化形式的方式,这取决于项目的具体constraints/circumstances甚至个人喜好。但是,我认为在决定 pro/contra in-class 初始值设定项时应考虑这些问题。
Pro:可读性。当您想了解 class 的用途时,您通常会从它的定义开始。在遍历数据成员时,让您的大脑在其类型旁边看到每个数据成员的初始值会很舒服,而不是扫描可能的多个构造函数。
Pro:当不需要 copy-pasting 另一个现有构造函数的初始值设定项时,添加更多构造函数会容易得多。使用 in-class 成员初始值设定项,您不太可能在添加构造函数时忘记一些初始化。
Pro:删除构造函数很容易。假设您从一个新的 class 开始,添加了一堆成员函数、一个构造函数和数据成员。然后你想起了 Scott Meyers 在 "How Non-Member Functions Improve Encapsulation" 中所说的话,你决定将成员函数变成免费的。你的类型现在看起来像一个愚蠢的
struct
与一些数据打包在一起 - 当它的构造函数不涉及任何业务逻辑时,你可能想要将类型转换为聚合:使用 in class 初始值设定项,您只需删除构造函数 - 完成。Contra:无论何时使用 in class 初始化器,都必须知道被初始化的数据成员的具体类型。当有问题的 class 定义在 header 中(最有可能),编译时间是一个问题(最有可能),有问题的数据成员有一个 heavy-weight 时,这可能会成为问题定义(有时)and/or 需要 non-trivial 依赖于构造(有时)。一个简单的准则可能是:在 Pimpl-idiom 有用的情况下,它比第 1.-3 点更重要。并且不排除 in-class 初始值设定项,因此请使用 Pimpl。
最后说明:核心指南建议在 C.48 中使用 in-class 初始值设定项,原因是:
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.