显式默认构造函数的目的 [英] Purpose of Explicit Default Constructors
问题描述
我最近注意到C ++ 0x中的一个类需要一个显式的默认构造函数.但是,我无法提出一种方案,在该方案中可以隐式调用默认构造函数.这似乎是一个毫无意义的说明符.我认为也许不允许Class c;
赞成Class c = Class();
,但是事实并非如此.
I recently noticed a class in C++0x that calls for an explicit default constructor. However, I'm failing to come up with a scenario in which a default constructor can be called implicitly. It seems like a rather pointless specifier. I thought maybe it would disallow Class c;
in favor of Class c = Class();
but that does not appear to be the case.
C ++ 0x FCD中的一些相关引号,因为它使我更容易浏览[如果不在同一位置,C ++ 03中也存在相似的文本]
Some relevant quotes from the C++0x FCD, since it is easier for me to navigate [similar text exists in C++03, if not in the same places]
12.3.1.3 [class.conv.ctor]
12.3.1.3 [class.conv.ctor]
默认构造函数可以是显式构造函数;这样的构造函数将用于执行默认初始化或值初始化(8.5).
A default constructor may be an explicit constructor; such a constructor will be used to perform default-initialization or value initialization (8.5).
接着提供了一个显式默认构造函数的示例,但它只是模仿了我上面提供的示例.
It goes on to provide an example of an explicit default constructor, but it simply mimics the example I provided above.
8.5.6 [decl.init]
8.5.6 [decl.init]
默认初始化T类型的对象的意思是:
To default-initialize an object of type T means:
-如果T是(可能是cv限定的)类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式不正确);
— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
8.5.7 [decl.init]
8.5.7 [decl.init]
要对T类型的对象进行值初始化,则意味着:
To value-initialize an object of type T means:
-如果T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数);
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
在两种情况下,标准调用都会调用默认构造函数.但是,如果默认构造函数不明确,将会发生这种情况.为了完整起见:
In both cases, the standard calls for the default constructor to be called. But that is what would happen if the default constructor were non-explicit. For completeness sake:
8.5.11 [decl.init]
8.5.11 [decl.init]
如果未为对象指定初始化程序,则该对象将被默认初始化;
If no initializer is specified for an object, the object is default-initialized;
据我所知,这只是没有数据的转换.这没有道理.我能想到的最好的方法是:
From what I can tell, this just leaves conversion from no data. Which doesn't make sense. The best I can come up with would be the following:
void function(Class c);
int main() {
function(); //implicitly convert from no parameter to a single parameter
}
但是显然,这不是C ++处理默认参数的方式.还有什么会使explicit Class();
的行为不同于Class();
?
But obviously that isn't the way C++ handles default arguments. What else is there that would make explicit Class();
behave differently from Class();
?
产生此问题的具体示例是std::function
[20.8.14.2 func.wrap.func].它需要几个转换构造函数,没有一个被标记为显式,但是默认构造函数是.
The specific example that generated this question was std::function
[20.8.14.2 func.wrap.func]. It requires several converting constructors, none of which are marked explicit, but the default constructor is.
推荐答案
这将声明一个显式的默认构造函数:
This declares an explicit default constructor:
struct A {
explicit A(int a1 = 0);
};
A a = 0; /* not allowed */
A b; /* allowed */
A c(0); /* allowed */
在没有参数的情况下(如以下示例所示),explicit
是多余的.
In case there is no parameter, like in the following example, the explicit
is redundant.
struct A {
/* explicit is redundant. */
explicit A();
};
在某些C ++ 0x草案(我相信它是n3035)中,它通过以下方式产生了不同:
In some C++0x draft (I believe it was n3035), it made a difference in the following way:
A a = {}; /* error! */
A b{}; /* alright */
void function(A a);
void f() { function({}); /* error! */ }
但是在FCD中,他们对此进行了更改(尽管,我怀疑他们没有考虑到这个特殊原因),因为这三种情况均 value-initialize 各自的对象.值初始化不会进行重载解析,因此不会在显式构造函数上失败.
But in the FCD, they changed this (though, I suspect that they didn't have this particular reason in mind) in that all three cases value-initialize the respective object. Value-initialization doesn't do the overload-resolution dance and thus won't fail on explicit constructors.
这篇关于显式默认构造函数的目的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!