好的,为C++中的无行为聚合(bundle-o-data)提供构造函数?

Emi*_*ier 5 c++

请参阅C++编码标准的规则#41 或Sutter的Gotw#70,其中指出:

使数据成员保密,除了无行为聚合(C样式结构).

为了方便起见,我经常想为这些C风格的结构添加一个简单的构造函数.例如:

struct Position
{
    Position(double lat=0.0, double lon=0.0) : latitude(lat), longitude(lon) {}
    double latitude;
    double longitude;
};

void travelTo(Position pos) {...}

main()
{
    travelTo(Position(12.34, 56.78));
}
Run Code Online (Sandbox Code Playgroud)

虽然可以更容易地动态构造Position,但构造函数也可以为我初始化默认的Position对象.

也许我可以关注std :: pair的例子并提供一个"makePosition"免费功能?NRVO应该和构造函数一样快,对吧?

Position makePosition(double lat, double lon)
{
    Position p;
    p.latitude = lat;
    p.longitude = lon;
    return p;
}

travelTo(makePosition(12.34, 56.78));
Run Code Online (Sandbox Code Playgroud)

通过添加那个可怜的小构造函数,我是否违背了"无行为聚合"概念的精神?

编辑:

是的,我知道Position p={12.34, 56.78}.但我不能travelTo({12.34, 56.78})用纯C结构.

编辑2:

对于那些对POD类型感兴趣的人:C++中的POD类型是什么?

追问: 我问一个后续问题这里是密切相关的这一个.

Ada*_*wen 7

我们定期为我们的聚合类型定义构造函数,没有任何负面影响.事实上,我能想到的唯一不利影响是,在性能危急情况下,您无法避免默认初始化,也无法在联合中使用该类型.

替代方案是初始化的大括号样式

Position p = {a,b};
Run Code Online (Sandbox Code Playgroud)

或免费的"制造"功能

Position makePosition(double a, double b)
{
    Position p = {a,b};
    return p;
}
Run Code Online (Sandbox Code Playgroud)

前者的问题是你不能用它来实例化一个临时传递给一个函数

void func(Position p)
{
    // ...
}

// func({a,b}) is an error
Run Code Online (Sandbox Code Playgroud)

后者在这种情况下很好,但对于懒惰的程序员来说,输入的次数要多一些.后一种形式(make函数)的问题在于它可能会忘记初始化您的数据结构.因为未初始化的变量让我感到相当不舒服,所以我更喜欢为我的聚合类型定义构造函数.

std :: make_pair存在的主要原因实际上不是出于这个原因(std :: pair有构造函数),但实际上因为要调用模板类型的构造函数,你必须传递模板参数 - 这很不方便:

std::pair<int,int> func()
{
    return std::pair<int,int>(1,2);
}
Run Code Online (Sandbox Code Playgroud)

最后,在您的示例中,您至少应该使构造函数显式化

explicit Position(double lat=0.0, double lon=0.0)
Run Code Online (Sandbox Code Playgroud)

否则你允许从double隐式转换为Position

Position p = 0.0;
Run Code Online (Sandbox Code Playgroud)

这可能会导致意外行为.实际上我会定义两个构造函数,一个用于初始化为零,另一个用两个值初始化,因为如果没有纬度和经度,Position构造可能没有多大意义.


小智 5

我经常为结构提供一个构造函数,没有任何问题.但是,如果构造函数是"非平凡的",那么结构不再被认为是POD类型,并且将对您可以使用它做什么进行限制.如果这对你来说是个问题(对我来说从来没有),那么make_XXXX功能显然是要走的路.