web-dev-qa-db-ja.com

明示的なデフォルトコンストラクタの目的

最近、明示的なデフォルトコンストラクターを必要とするC++ 0xのクラスに気づきました。ただし、デフォルトのコンストラクターを暗黙的に呼び出すことができるシナリオを思い付くことができません。それはかなり無意味な指定子のようです。 Class c = Class();を優先して_Class c;_を許可しないかもしれないと思いましたが、そうではないようです。

ナビゲートしやすいので、C++ 0xFCDからのいくつかの関連する引用[同じ場所にない場合でも、C++ 03に同様のテキストが存在します]

12.3.1.3 [class.conv.ctor]

デフォルトのコンストラクターは、明示的なコンストラクターの場合があります。このようなコンストラクターは、デフォルトの初期化または値の初期化(8.5)を実行するために使用されます。

明示的なデフォルトコンストラクターの例を提供し続けますが、それは単に上記で提供した例を模倣しています。

8.5.6 [decl.init]

タイプTのオブジェクトをデフォルトで初期化するには、次のことを意味します。

— Tが(おそらくcv修飾された)クラス型である場合(第9節)、Tのデフォルトコンストラクターが呼び出されます(Tにアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式になります)。

8.5.7 [decl.init]

タイプTのオブジェクトを値初期化するということは、次のことを意味します。

— Tがユーザー提供のコンストラクター(12.1)を持つ(おそらくcv修飾された)クラスタイプ(条項9)の場合、Tのデフォルトコンストラクターが呼び出されます(Tにアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式になります) );

どちらの場合も、標準ではデフォルトのコンストラクターが呼び出される必要があります。しかし、デフォルトのコンストラクターが非明示的である場合、それが起こります。完全を期すために:

8.5.11 [decl.init]

オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。

私の知る限り、これはデータなしからの変換を残すだけです。これは意味がありません。私が思いつくことができる最高のものは次のとおりです:

_void function(Class c);
int main() {
  function(); //implicitly convert from no parameter to a single parameter
}
_

しかし、明らかにそれはC++がデフォルトの引数を処理する方法ではありません。 explicit Class();Class();とは異なる動作にする他に何がありますか?

この質問を生成した特定の例は、_std::function_ [20.8.14.2func.wrap.func]でした。いくつかの変換コンストラクターが必要であり、いずれも明示的にマークされていませんが、デフォルトのコンストラクターはです。

37

これにより、明示的なデフォルトコンストラクタが宣言されます。

struct A {
  explicit A(int a1 = 0);
};

A a = 0; /* not allowed */
A b; /* allowed */
A c(0); /* allowed */

次の例のようにパラメータがない場合、explicitは冗長です。

struct A {
  /* explicit is redundant. */
  explicit A();
};

一部のC++ 0xドラフト(n3035だったと思います)では、次のように違いがありました。

A a = {}; /* error! */
A b{}; /* alright */

void function(A a);
void f() { function({}); /* error! */ }

しかし、FCDでは、3つのケースすべてこれを変更しました (ただし、この特定の理由を念頭に置いていなかったと思います) )value-initializeそれぞれのオブジェクト。値の初期化は過負荷解決のダンスを行わないため、明示的なコンストラクターで失敗することはありません。