我知道我们可以同时调用构造函数的概念 Explicitly
和 Implicitly
,并且我已经测试了这两种场景(通常到现在我的所有目的都通过调用构造函数 Implicitly
),但我想知道每当我们创建 objects
时,构造函数都会被隐式调用,那么调用构造函数 Explicitly
的主要原因是什么。当我们调用构造函数 Explicitly
而不是 Implicit Call
时,它提供了什么优点或缺点?
例子
class integer
{
int m ,n;
public:
integer (int x , int y);
};
integer :: integer (int x , int y )
{
m=x; n = y;
}
现在如果我打电话
integer int1 = integer( 0 , 100); // Explicit Call
integer int1(1,100); // implicit call
原文由 Tejendra 发布,翻译遵循 CC BY-SA 4.0 许可协议
这里有两个不同的问题,因为您对 显式 和 隐式 的定义与标准定义不匹配(大多数现有答案都基于标准定义,在您添加包含您自己的 显式 和 隐式 定义的示例之前编写)。
好的,让我们首先考虑一下您对 explicit 的定义,这将是(我猜您之所以称它为 explicit 是因为您明确编写了类型名称?):
与您对 隐式 的定义相比:
在这种情况下,第一个 “显式” 调用确实比第二个 “隐式” 调用没有任何优势。但是还是有区别的。第一个实际上使用双参数构造函数创建了一个临时对象,然后使用复制构造函数创建
int1
。尽管实际上编译器通常会优化掉这个额外的副本,但如果您的副本构造函数是私有的,它仍然无法工作,而第二个只需要双参数构造函数(您甚至可以将此视为缺点)。但现在到了 显式 和 隐式 的实际标准定义。 显式 构造函数调用是任何构造函数调用,好吧,显式调用。实际上,每当您使用括号语法
()
创建一个对象时,您显式调用构造函数,否则它是 隐式 构造函数调用(也就是说,由编译器在幕后完成):因此,唯一可以 隐式 调用的构造函数是默认构造函数和任何单参数构造函数(包括复制和移动构造函数)。这方面的一个特殊问题是单参数构造函数不是复制/移动构造函数:
这允许编译器隐式调用构造函数来转换类型,因此任何
int
都 可以隐式转换为integer
:要禁止这种行为,您必须标记构造函数
explicit
:这只允许 显式 调用它(例如
func(integer(42))
)(但我想你已经知道了)。这样做的好处是它不会在幕后引入未被注意到/不需要的转换,这可能会导致各种难以发现的问题和关于重载解决方案的歧义。因此,通常的做法是标记任何转换构造函数(单参数非复制/移动构造函数)explicit
,而且很可能也是 C++11 最终引入explicit
转换的原因运营商。因此,总而言之,根据您的定义和示例,使用
integer int1 = integer(1, 100);
而不是integer int1(1, 100);
确实没有任何优势,尽管它会产生(通常不相关的)差异。但是根据标准定义, 显式 构造函数调用比 隐式 调用有很多优势,因为 显式 构造对象的唯一方法是使用 _显式构造函数调用_,而 隐式构造函数调用 仅在某些情况下在幕后完成情况,并且仅适用于零参数和一参数构造函数(正如 aschepler 已经指出的那样)。并且将转换构造函数显式标记为
explicit
具有不允许在幕后进行不需要的隐式转换的优点。