14

C++でリテラル クラスがいつ必要になるか教えてもらえますか? constexprコンストラクター、constexpr メンバー から少し混乱しており、ポイントがわかりません。実用的な使い方を見てみたい。

また、セットメンバー関数がconstexprである必要があるかどうかも知りたいです。

constexpr void set_num(int a) { num = a; }
4

3 に答える 3

12

C++03 では、このオブジェクトは動的に初期化されます

struct Data {
  int i;
  int j;
};
Data init_data();  // calculate something
const Data data = init_data();

つまり、プログラムの開始時、main実行前に関数が呼び出され、オブジェクトが初期化されます。

C++11 では、オブジェクトは静的初期化の形式である定数初期化を持つことができます。これは、その値がコンパイル時に設定され、プログラムが開始される前に初期化されることを意味します。これは、特に静的初期化順序の大失敗を回避するのに役立ちます。型が定数の初期化を確実に取得するには、定数式によって初期化する必要があるため、コンストラクターが必要であり、完全な式で呼び出される関数はすべて関数でなければなりません。constexprconstexpr

Dataは自明なので、暗黙的に宣言されたコンストラクターはコンストラクconstexprターであるため、グローバルを一定の初期化にするには、関数にする必要があります。datainit_data()constexpr

struct Data {
  int i;
  int j;
};
constexpr Data init_data();  // calculate something
constexpr Data data = init_data();

リテラル型の利点は、そのような型を他の定数式、つまりコンパイル時の定数を必要とするコンテキストで使用できることです。オブジェクトをコンパイル時の定数として取得したのでdata、それを他の定数式で使用して、他のコンパイル時の定数を初期化することができます。

const int i = ::data.i;

また、Dataクラス内初期化子を使用して静的データ メンバーの型を使用できます。

struct MoreData {
  static constexpr Data zerozero = Data{};  // OK, Data is a literal type
};

Dataリテラル型でない場合は、次のように記述する必要があります。

struct MoreData {
  static const Data zerozero;
};

// in moredata.cc
const Data MoreData::zerozero = Data{};

そして、ヘッダーのみを参照するコードは、の値を認識せずMoreData::zerozero、コンパイル時の最適化で使用できません。

したがって、「リテラル型」規則の利点は、定数式で使用できる新しいクラス型を定義できることです。C++03 では、整数などの非常に少数の型のみを定数式で使用できました。たとえば、1または0x23または整数型のコンパイル時定数などの整数リテラルです。C++11 では、コンストラクター (関数で表現できるもの) に適度に複雑なロジックを含めることができる独自の型を作成できますがconstexpr、コンパイル時の定数として使用することもできます。

また、セットメンバー関数が constexpr である必要があるかどうかも知りたいです。

メンバー関数はメンバー関数のconstexpr特殊なケースであるconstため、型の (非-mutable) メンバーを変更することはできません。オブジェクトを変更するセッター関数を const にすることはできません。

クラスがリテラル型であるためには、少なくとも 1 つのconstexprコンストラクターを持つなど、いくつかの規則に従う必要があります。これは、その型のすべてのオブジェクトが定数でなければならないという意味ではなく、その型のオブジェクトがそのように宣言され、クラスのコンストラクターの 1 つを使用して初期化されている場合、その型のオブジェクトを定数にすることができることを意味します。例をもう一度使用すると、プログラム内のほとんどのオブジェクトは定数ではありません。constexprconstexprconstexprData

Data d = { 0, 1 };
d.i = d.i + 5;

したがって、オブジェクトを変更する関数であるセッターを追加した場合、その型の非 const オブジェクトでのみ使用する意味があり、型を変更する他の関数と同様に、そうすべきではありません

于 2013-01-14T01:01:22.480 に答える
7

constexpr は、数値制限を使用する場合の C++98 の問題を修正します。C++11 より前は、次のような式

std::numeric_limits<short>::max()

マクロとほぼ同等ですが、整数定数としては使えませんINT_MAX。C++11 では、そのような式は constexpr として宣言されるため、たとえば、配列を宣言したり、コンパイル時の計算 (メタプログラミング)で使用したりできます。

std::array<float,std::numeric_limits<short>::max()> a;
于 2013-01-13T23:28:37.027 に答える
3

クラスの大きな利点は、constexprクラスを .ro データに入れることができることです。これにより、実行可能ファイルのサイズが縮小され、パフォーマンスが向上します。特に。幾何学的な型、例えば類似の「単純な」型の場合、「魔法の」数を取り除くこともできるので、これは非常に便利です。たとえばhttps://www.kdab.com/kdab-contributions-to-qt-5-0-part-4/を参照してください。

于 2013-01-14T00:18:14.617 に答える