Giriş
Aggreate POD veya array olabilir. Array için olan yazıyı ayırmaya karar verdim. Brace Initialization - Array Aggregate yazısına taşıdım.
1. Aggregate Nedir
C++11 ile tanım olarak şöyle.
Açıklaması şöyle.
Elimizde şöyle bir kod olsun. a sınıfındaki constructor explicit olduğu için hata alırız.
Kalıtım sadece C++17 ile geldiği için açıklaması şöyle
Elimizde şöyle bir kod olsun. İlk kod kalıtım olduğu halde aggregate initialization kullanıyor.
Örnek
Açıklaması şöyle. C++20 ile artık aggregate initializaton çalışmıyor.
Örnek
Şu kod derlenmez.
Elimizde şöyle bir kod olsun.
Elimizde şöyle bir kod olsun
Member sayısından Daha Az Değer Belirtmek - C++ 98
Bu yöntem C dilinde de aynı. Açıklaması şöyle
Şöyle yaparız. Buradaki örnek C kodu. Hem struct hem de array olan değişken ilklendiriliyor.
Şöyle yaparız.
Member Sayısından Daha Az Değer Belirtmek - C++11
Sequence Point
Aggreate POD veya array olabilir. Array için olan yazıyı ayırmaya karar verdim. Brace Initialization - Array Aggregate yazısına taşıdım.
1. Aggregate Nedir
C++11 ile tanım olarak şöyle.
C++17 ile tanım olarak şöyle. Yani artık public inheritance olabiliyor.An aggregate is an array or a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions.
no virtual, private, or protected (since C++17) base classes
Örnek - C++14 Default Member Initializer'a İzin Verir
C++11 açısından default member initializer kullanıldığı için şu bir aggregate değil. C++14 açısından aggregate sayılırclass S
{
public:
int a = 0;
};
Aggregate ve Initializer ListAçıklaması şöyle.
When you initialize it using an initializer list, the elements in the list will initialize the first n members of the aggregate, where n is the number of elements in the list. The remaining elements of the aggregate are copy-list-initialized.Örnek - Explicit Constructor Olamaz
Elimizde şöyle bir kod olsun. a sınıfındaki constructor explicit olduğu için hata alırız.
class a
{
public:
explicit a () {}
};
struct b
{
a member;
};
int main() {
b foo {};
}
Bu kod derlenmez. Hata çıktısı şöyledir."chosen constructor is explicit in copy-initialization"Aggregate ve Kalıtım
Kalıtım sadece C++17 ile geldiği için açıklaması şöyle
Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
Örnek - C++17 Kalıtıma İzin Verir
Dolayısıyla C++17 açısından B bir aggregate kabul edilir.struct A { int a; };
struct B : A {};
Örnek - - C++17 Kalıtıma İzin Verir
struct Base0 {};
struct Base1 {};
template<typename... Ts>
struct Derived: Ts... {};
int main() {
Derived<Base0, Base1> d0 {Base0{}, Base1{}}; // OK
Derived<Base0, Base1> d1 (Base0{}, Base1{}); // ERROR
}
User Provided Constructor Yoksa ve User Declared Constructor Varsa
C++20 ile geriye uyumluluk bozuluyor. C++17'ye kadar derlenen kodlar artık derlenmiyor.
Örnek
Açıklaması şöyle
Class Ax is an aggregate in C++11, C++14 and C++17, as it has no user-provided constructors, which means that Ax{} is aggregate initialization, bypassing any user-declared constructors, even deleted ones...In C++20 the rules were changed so that any user-declared constructors prevent the type from being an aggregate, and so the example will fail to compile.
Şu kod C++17'ye kadar derlenir. C++20 ile derlenmez.
class Ax
{
public:
Ax() = delete;
Ax(Ax const&)=delete;
Ax(Ax&&)=delete;
void operator=(Ax const&)=delete;
void operator=(Ax&&)=delete;
void print()
{
cout << "Hello \n";
}
};
int main(int argc, char** argv)
{
Ax{}.print();
return 0;
}
Açıklaması şöyle. C++20 ile artık aggregate initializaton çalışmıyor.
C++ currently allows some types with user-declared constructors to be initialized via aggregate initialization, bypassing those constructors. The result is code that is surprising, confusing, and buggy. This paper proposes a fix that makes initialization semantics in C++ safer, more uniform,and easier to teach. We also discuss the breaking changes that this fix introduces.
Örnek
Şu kod derlenmez.
struct X {
int i{4};
X() = default;
};
int main() {
X x1(3); // ill-formed - no matching c’tor
X x2{3}; // compiles!
}
Şu kod derlenmez.
struct Foo
{
Foo() = default;
int bar;
};
auto test = Foo { 0 };
Default Constructor'ı SilmekElimizde şöyle bir kod olsun.
struct Foo {
Foo() = delete;
int i;
};
Şöyle yaparız böylece üye alanlara bir değer atanır.Foo f2{}; // i initialized to zero
Foo f3{42}; // i initialized to 42
Şu kod derlenmez.Foo f1; // i uninitialized
Public Olmayan Constructor - C++17Elimizde şöyle bir kod olsun
struct B {
protected:
B() { }
};
struct D : B { };
auto d = D{};
Açıklaması şöyleIn C++14, D is not an aggregate because it has a base class, so D{} is "normal" (non-aggregate) initialization which invokes D's default constructor, which in turn invokes B's default constructor. This is fine, because D has access to B's default constructor.2. Brace Initialization Örnekleri
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual). D is now an aggregate, which means that D{} is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B's constructor (it is protected), so we cannot invoke it, so it is ill-formed.
Member sayısından Daha Az Değer Belirtmek - C++ 98
Bu yöntem C dilinde de aynı. Açıklaması şöyle
The {0} initializer to initialize all objects in an aggregate (meaning array or struct) is 100% standard in any version of C. The syntax allows you to omit the braces for sub-aggregates.Örnek
Şöyle yaparız. Buradaki örnek C kodu. Hem struct hem de array olan değişken ilklendiriliyor.
struct my_type my_thing[NUMBER_OF_THINGS] = {0};
ÖrnekŞöyle yaparız.
SHELLEXECUTEINFO sexi = {0};
Boş aggregate initializer da aynı şeyi yapar.SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};
Burada dikkat edilmesi gereken nokta alignment yüzünden yerleştirilen aradaki byte'lar aggregate ile sıfırlanmaz. Bu iş için memset yapmak gerekir. Yanistruct foo
{
char c;
int i;
};
foo a = {0};
ilefoo a;
memset(&a,0,sizeof(a));
farklı şeylerdir.Member Sayısından Daha Az Değer Belirtmek - C++11
Açıklaması şöyle.
C++14 ile şöyle yapabiliyoruz. Elimizde şöyle bir struct olsun
Member Sayısından Daha Az Değer Belirtmek - C++14If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be default-initialized. Example:struct S { int a; char* b; int c; }; S ss = { 1, "asdf" };
initializesss.a
with1
,ss.b
with"asdf"
, andss.c
with the value of an expression of the formint()
, that is,0
.
C++14 ile şöyle yapabiliyoruz. Elimizde şöyle bir struct olsun
struct PointA
{
double x = 0.0;
double y = 0.0;
};
Şöyle yapabiliriz.PointA pA3 = { 2.0 }; // {2., 0.}
Member Sayısı Kadar Değer Belirtmek
Tüm elemanlar belirtilen değerlere sahip olur. Örnek
Elimizde şöyle bir kod olsun
Elimizde şöyle bir kod olsun
template <typename T, size_t dim1, size_t dim2>
struct MyStruct
{
public:
T m_data[dim1][dim2];
};
Şöyle yaparız
MyStruct<int, 3, 3> s =
{{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
}};
Açıklaması şöyle.
Liste içinde aynı değişken değer değiştirerek tekrar kullanılabilir. Şöyle yapabiliriz.10) In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the brace-enclosed comma-separated list of initalizers.
struct T t = { i, ++i };
Hiç yorum yok:
Yorum Gönder