结构的构造函数,不执行任何操作

时间:2012-07-18 08:37:15

标签: c++ constructor struct

编辑:为了清楚,结构没有做任何事情,因为它没有任何功能。我想我给人的印象是我认为使用初始化列表并将构造函数的主体留空是问题。

假设我正在使用一个结构来保存两个值,我有一个构造函数,所以我可以创建一个像这样的任意结构:

struct twoValues
{
    int x;
    int y;

    twoValues(int x_, int y_):y(y_),x(x_)
    {}
};

someFunction(twoValues(1,2));

这使我免于必须这样做:

twoValues anInstance;
anInstance.x=1;
anInstance.y=2;
someFunction(anInstance);

编辑:你们都是正确的,我也可以使用以下内容进行初始化:

twoValues anInstance = {1,2};

我认为没有错,但我从C ++测试得到了一些反馈,其中一个负反馈标记是“没有做任何事情的结构的构造函数”。我与测试我的人接触有限,因此从未问过为什么。

这是一件坏事,为什么?我宁愿继续这样做。

8 个答案:

答案 0 :(得分:17)

这取决于结构的用途。正如其他人所说, 构造函数意味着该类不再是POD,而且 聚合初始化不能用于它。特别是你 不能在命名空间范围内拥有像:

TwoValues const table[] =
{
    { 1, 2 },
    { 3, 4 },
    // ...
};

你可以:

TwoValues const table[] =
{
    TwoValues(  1, 2  ),
    TwoValues(  3, 4  ),
    // ...
};

但它更详细,它意味着动态初始化,这可能是 导致初始化问题的顺序。

另一方面,如果没有构造函数,则无法创建临时文件 飞行中的实例。而不是:

extern void f( TwoValues const& );
//  ...

f( TwoValues( 1, 2 ) );

你必须写:

extern void f( TwoValues const& );
//  ...

TwoValues tmp = { 1, 2 };
f( tmp );

如果对象是动态分配的,那就更糟了,因为你 要么先分配,要么初始化,要么创建临时的 在上面,然后编写new TwoValues( tmp )并使用隐式副本 构造

你必须选择。取决于结构用于什么,一个或 另一个是首选;一方面,我有很多结构 仅在静态表中使用,并且故意没有 构造函数(仅包含支持静态的类型) 初始化),并使用它们来配置代码。在另一 我也有很多类似于内部的结构 树或图中Node的行;这几乎总是有一个 构造函数,以便于在运行中创建它们。没有 “正确”回答,而不知道结构在你的角色中的作用 应用

答案 1 :(得分:13)

声明一个空构造函数有副作用..

即使你的构造函数有一个空 body ,它仍然被认为是构造函数,因此某些对象属性将会丢失 - 例如对象是POD。

有些情况需要使用普通旧数据 - 类型,这可能会使您无需在没有特定原因的情况下完成您的操作。

在下一节中阅读更多关于初始化而不使用defult构造函数。


&&

您可以使用值初始化您的成员,而无需显式定义“不执行任何操作的构造函数”,只需使用下面代码段中的大括号初始化语法。

struct Obj {
  int x, y;
};

Obj a = {1,3}; /* a.x = 1, a.y = 2 */

没有构造函数的缺点是在编写 C ++ 03 时,在某些情况下无法使用= { ... }初始化对象。

C ++ 11 为您解决此问题,请参阅相关示例的下一部分。


在C ++ 11中,使用大括号(= { ... })的初始化功能得到了增强。

如下面的片段所示,即使我们使用与本文前面相同的初始化形式,也会调用Obj的定义构造函数。

struct DoubleBoth {
  DoubleBoth (int x, int y)
    : x(x*2), y(y*2) 
  {}  

  int x, y;
};

下面的代码段在C ++ 11之前都是非法的

DoubleBoth a = {1,2}; /* a.x = 2, a.y = 4 */

struct Wrapper {
  Wrapper ()
    : value {3,4}
  {}

  DoubleBoth value;
};

void func (DoubleBoth v = {1,2}) {  // c++11 only
  ...
}

func ({4,5}); // c++11 only, c++03 requires `DoubleBoth obj (0,1); func (obj);`

答案 2 :(得分:7)

您已将twoValues作为POD停止,并且已阻止结构的实例进行默认值或值初始化,这通常是所需的属性。就个人而言,如果你需要一个简单的C ++ 03友好方法,我宁愿有一个免费的函数来制作临时实例。

E.g。

twoValues makeTwoValues(int x_, int y_)
{
    twoValues tmp = { x_, y_ };
    return tmp;
}

void f() {
    someFunction(makeTwoValues(1,2));
}

E.g。初始化twoValues

类型的成员
class X {
    twoValues tv;
public:
    X(int x, int y) : tv(makeTwoValues(x, y)) {}
};

答案 3 :(得分:7)

拥有这种构造函数要比使用列表初始化更安全。

使用列表初始化时:

twoValues anInstance = {1, 2};

这实际上取决于结构中成员的顺序。在大多数情况下,这是完全随机的。

如果其他程序员碰巧添加了其他成员,或者按字母顺序对成员进行排序,则无法正常工作。

有一个构造函数可以通过NAME将值分配给正确的成员更加安全。

答案 4 :(得分:4)

可能是因为你可以像这样初始化它:

twoValues anInstance = {1, 2};

但是,如果没有构造函数,则无法在C ++ 03中的另一个struct的初始化列表中初始化anInstance。例如:

struct Bar {
  twoValues v_;
  Bar() : v_(1,2) {} // error!
  Bar() { v_ = {1,2}; } // have to assign value in constructor body
  Bar() : v_{1,2} {} // OK in C++11
};

所以实际上构造函数做了一些事情,它确实在C ++ 03中起到了非常有用的作用。它在C ++ 11中不是一个问题。

答案 5 :(得分:2)

这个构造函数没有错。

此外,它执行某些操作,它会影响x和y的值,这就是我对此类构造函数的期望。

但是,也许你的公司有一些编码规则说你应该采取另一种方式。在这种情况下,我建议你问那些给你反馈并进行必要修改的人。

答案 6 :(得分:2)

构造函数使结构成为非POD,在某些情况下可能并不理想。

如果你的结构没有构造函数,那么你的结构将是POD 1 ,你将被允许像这样初始化:

twoValues anInstance = {1,2}; //C++03 and C++11 both!
twoValues anInstance {1,2};   //C++11 only

哪个好。

1。实际上还有其他一些东西使得结构非POD。所以只是因为你的struct没有构造函数并不一定意味着它是POD。您希望this post知道其他内容是什么。

答案 7 :(得分:0)

结构可以有构造函数,语法与C ++中的类相同。类和结构之间的区别在于,默认情况下类成员是私有的,而struct-members默认为public,但是Unions不允许结构中的构造函数。你可以在联盟上创建一个构造函数。