1

所以如果我有课

class Transaction {

int no;
char dollar;

public:

    Transaction();
    ~Transaction();
}

在我的构造函数/析构函数中

Transaction::Transaction {
    cout << "Entering constructor" << endl;
}

Transaction::~Transaction {
    cout << "Leaving program" << endl;
}

该代码是否足以让我的构造函数和析构函数工作?即使我在构造函数中没有声明任何内容,它是否会将我的类中的数据成员设置为安全状态?

4

3 回答 3

5

如果您提供构造函数而不为所述子对象指定初始化程序,则每个子对象都将被默认初始化。

该标准第 8.5 节规定:

如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。[ 注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。——尾注]

然后

默认初始化类型的对象T意味着:

  • ifT是(可能是cv-qualified)类类型,T调用默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);
  • 如果 T 是数组类型,则每个元素都是默认初始化的;
  • 否则,不执行初始化。

如果程序要求对 const 限定类型的对象进行默认初始化TT则应是具有用户提供的默认构造函数的类类型。

初始化子对象有两种方法:在ctor-initializer-list 中,以及在成员声明中的大括号或相等初始化器中(对于非静态成员,后者在 C++11 中是新的)。

实际上,这意味着当您不提供初始值设定项时,原始类型的变量(例如intand char)会保留之前留在内存中的任何值。在大多数情况下,很难预测这将是什么值,但您应该知道它可能是剩余的敏感数据,例如密码。

在初始化静态存储持续时间的变量(例如命名空间范围内的对象及其成员)的情况下,标准进一步提供(同一部分):

在任何其他初始化发生之前,在程序启动时,每个静态存储持续时间的对象都被初始化为零。

如果您没有定义构造函数,这与值初始化期间发生的情况略有不同:

对类型对象进行值初始化T意味着:

  • 如果T是具有用户提供的构造函数的(可能是cv 限定的)类类型,则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化格式错误);
  • ifT是没有用户提供的构造函数的(可能是cv 限定的)非联合类类型,则该对象被零初始化,并且如果T的隐式声明的默认构造函数是非平凡的,则调用该构造函数。
  • 如果T是数组类型,则每个元素都是值初始化的;
  • 否则,对象被零初始化。

但效果是一样的——原始成员设置为零,所有其他成员都调用了它们的零参数构造函数。

nneonneo 建议显式初始化所有成员是好的,因为仅对静态存储持续时间的变量进行零初始化通常会导致难以发现的错误。但是使用大括号或相等初始化器技术是完全可行的:

class Transaction
{
    int no = 0;
    char dollar = 0;
public:

    Transaction();
    ~Transaction();
}
于 2013-03-01T02:30:37.787 回答
1

您的类只有简单的数据成员,因此您甚至不需要(或不应该想要)析构函数。

但是,您应该在构造函数中初始化数据成员:

Transaction::Transaction()
  : no(0), dollar('$') {
    cout << "Entering constructor" << endl;
}

否则,它们将不会被初始化,并且可能包含随机值(如果您不在构造函数中初始化它们,C++ 不保证将原始非静态成员初始化为任何特定值)。如果您有指针成员,这可能会特别阴险。

于 2013-03-01T02:22:20.847 回答
0

不,它不必有代码。事实上,在大多数语言中,您可以将其省略,它会正确构建类。

于 2013-03-01T02:19:39.773 回答