Aşağıdaki tanımlar arasında bir fark var mı?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Değilse, C ++ 11'de hangi stil tercih edilir?
Aşağıdaki tanımlar arasında bir fark var mı?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Değilse, C ++ 11'de hangi stil tercih edilir?
Yanıtlar:
Bir fark olduğuna inanıyorum. Onları daha kolay konuşabilmemiz için onları yeniden adlandıralım:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Hem PI1
ve PI2
bunları değiştiremez, yani sabittir. Ancak sadece PI2
derleme zamanı sabiti. Bu edecektir derleme sırasında başlatılır. PI1
derleme zamanında veya çalışma zamanında başlatılabilir. Ayrıca, yalnızca PI2
derleme zamanı sabiti gerektiren bir bağlamda kullanılabilir. Örneğin:
constexpr double PI3 = PI1; // error
fakat:
constexpr double PI3 = PI2; // ok
ve:
static_assert(PI1 == 3.141592653589793, ""); // error
fakat:
static_assert(PI2 == 3.141592653589793, ""); // ok
Hangisini kullanmalısınız? İhtiyaçlarınızı karşılayanı kullanın. Derleme zamanı sabitinin gerekli olduğu bağlamlarda kullanılabilen bir derleme zaman sabitine sahip olduğunuzdan emin olmak istiyor musunuz? Çalışma zamanında yapılan bir hesaplama ile ilklendirmek ister misiniz? Vb.
const int N = 10; char a[N];
works ve dizi sınırları derleme zamanı sabitleri olmalıdır.
PI1
bir dizide kullanmak için derleme zamanı integral sabitine dönüştürmeme izin veriyor, ancak tür olmayan bir integral şablon parametresi olarak kullanım için değil. Yani derleme-zaman PI1
ayrılmaz bir tür dönüştürülebilir bana biraz hit & miss gibi görünüyor.
enum
başlatıcı olarak kullanım, const
ve arasındaki önemli iki farktır constexpr
(ve her ikisi de işe yaramaz double
).
1 / PI1
ve 1 / PI2
farklı sonuçlar verebilir. Ancak bu teknikliğin bu cevaptaki tavsiye kadar önemli olduğunu düşünmüyorum.
constexpr double PI3 = PI1;
benim için doğru çalışıyor. (MSVS2013 CTP). Neyi yanlış yapıyorum?
Burada bir fark yok, ancak bir yapıcıya sahip bir tipiniz olduğunda önemli.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
sabittir, ancak derleme zamanında başlatılacağına söz vermez. s1
işaretlidir constexpr
, bu yüzden sabittir ve S
'yapıcısı da işaretlendiğinden constexpr
derleme zamanında başlatılır.
Çoğunlukla bu, çalışma zamanında başlatma zaman alıcı olacağı zaman önemlidir ve bu işi derleyici üzerine de itmek istersiniz, burada da zaman alıcıdır, ancak derlenmiş programın yürütme süresini yavaşlatmaz.
constexpr
, nesnenin derleme zamanı hesaplamasının imkansız olması durumunda teşhise yol açacağıydı. Daha az net olan , parametrenin şu şekilde değil bildirilmesi gerektiği gibi, sabit bir parametre bekleyen bir işlevin derleme zamanında yürütülüp yürütülemeyeceğidir : yani, çağırırsam derleme zamanında yürütülür mü? const
constexpr
constexpr int foo(S)
foo(s0)
foo(s0)
Derleme zamanında yürütülüp yürütülmeyeceğinden şüpheliyim , ancak asla bilemezsiniz: bir derleyicinin bu tür optimizasyonları yapmasına izin verilir. Kesinlikle, ne gcc 4.7.2 ne de clang 3.2 constexpr a = foo(s0);
constexpr , derleme sırasında sabit ve bilinen bir değeri belirtir.
const yalnızca sabit olan bir değeri gösterir; derleme sırasında bilmek zorunlu değildir.
int sz;
constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
Const'un constexpr ile aynı garantiyi sağlamadığını unutmayın, çünkü const nesnelerinin derleme sırasında bilinen değerlerle başlatılması gerekmez.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation
Tüm constexpr nesneleri sabittir, ancak tüm const nesneleri constexpr değildir.
Derleyicilerin bir değişkenin derleme zamanı sabitleri gerektiren bağlamlarda kullanılabilecek bir değere sahip olmasını garanti etmesini istiyorsanız, ulaşılacak araç const değil constexpr'dir.
Bir comptexpr sembolik sabitine derleme zamanında bilinen bir değer verilmelidir. Örneğin:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
Davalarını için nereye derleme zamanında bilinmemektedir ancak, C ++ sunuyor başlatmasından sonra sabit ikinci bir formu (a hiç değişmez bir değerle başlatılan bir “değişken” değeri const ). Örneğin:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Bu tür “ sabit değişkenler” iki nedenden dolayı çok yaygındır:
Kaynak: "Programlama: C ++ Kullanarak İlkeler ve Uygulamalar" Stroustrup