构造函数/析构函数是否必须有代码,或者函数是否足够?
Does a constructor / destructor have to have code, or is the function enough?
如果我有一个class
class Transaction {
int no;
char dollar;
public:
Transaction();
~Transaction();
}
在构造函数/析构函数
中Transaction::Transaction {
cout << "Entering constructor" << endl;
}
Transaction::~Transaction {
cout << "Leaving program" << endl;
}
这段代码足以让构造函数和析构函数工作吗?即使我在构造函数中没有声明任何内容,它会将类中的数据成员设置为安全状态吗?
如果您提供了一个构造函数而没有为所述子对象指定初始化式,则每个子对象将被默认初始化。
标准第8.5节规定:
如果对象没有指定初始化式,则默认初始化该对象;如果不进行初始化,自动或动态存储时长的对象的值不确定。[注:具有静态或线程存储时间的对象是零初始化的,参见3.6.2。]
和
初始化子对象有两种方法:在元素初始化器列表中,以及在成员声明中的大括号或相等初始化器中(对于非静态成员,后者是c++ 11中新增的)。default-initialize类型为
T
的对象意味着:
- 如果
T
是(可能cv限定的)类类型,则调用T
的默认构造函数(如果T没有可访问的默认构造函数,则初始化是病态的);- 如果T是数组类型,则每个元素默认初始化;
- 否则,不初始化。
如果程序调用具有const限定类型
T
的对象的默认初始化,则T
必须是具有用户提供的默认构造函数的类类型。
在实践中,这意味着当您不提供初始化式时,原始类型的变量,如int
和char
,将保留先前留在内存中的任何值。在大多数情况下,很难预测该值是什么,但您应该意识到它可能是剩余的敏感数据,例如密码。
对于静态存储时间变量的初始化(如命名空间范围内的对象及其成员),标准进一步规定(同一节):
在程序启动时,在进行任何其他初始化之前,每个静态存储持续时间的对象都进行零初始化。
如果没有定义构造函数,这与值初始化期间发生的情况略有不同:
对
T
类型的对象进行值初始化意味着:
- 如果
T
是具有用户提供的构造函数的类类型(可能是cv限定的),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);- 如果
T
是一个(可能cv限定的)没有用户提供的构造函数的非联合类类型,则对象为零初始化,如果T
隐式声明的默认构造函数是非平凡的,则调用该构造函数。- 如果
T
是数组类型,则每个元素都是值初始化的;- 否则,对象为零初始化。
,但效果是一样的——基本成员被设置为0,所有其他成员都调用它们的零参数构造函数。
nneonneo显式初始化所有成员的建议是好的,因为只对静态存储持续时间的变量进行零初始化通常会导致难以发现的bug。但是使用大括号或相等初始化器技术是完全可行的:
class Transaction
{
int no = 0;
char dollar = 0;
public:
Transaction();
~Transaction();
}
你的类只有简单的数据成员,所以你甚至不需要(或者不应该想要)析构函数。
但是,应该在构造函数中初始化数据成员:Transaction::Transaction()
: no(0), dollar('$') {
cout << "Entering constructor" << endl;
}
否则,它们将不会被初始化,并且可能包含随机值(如果不在构造函数中初始化原始非静态成员,则c++不保证将其初始化为任何特定值)。如果您有指针成员,这可能特别危险。
不,它不需要有代码。事实上,在大多数语言中,你可以省略它,它会正确地构造类。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 函数作为模板参数,是否对返回类型强制约束
- visual是否可以在c++中创建一个接收无限数量相同类型(或至少相当数量)参数的函数
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 函数是否可以访问传递给main()的参数
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 在这种情况下,java对象是否可以调用本机函数
- 检查函数返回类型是否与STL容器类型值相同
- 根据某个函数是否存在启用模板
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- 无论如何,我可以确定构造函数是否存在吗?
- 是否可以将函数导入命名空间,但不能导出它?
- 返回指向对象的指针的函数调用是否为 prvalue?
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 是否有任何建议来统一函数类型限定符并简化可恶的函数类型?
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本