default
Bir sınıftaki işlev bildirimlerinin yanında kullanıldığını gördüm . Bu ne işe yarıyor?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
default
Bir sınıftaki işlev bildirimlerinin yanında kullanıldığını gördüm . Bu ne işe yarıyor?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Yanıtlar:
Bu yeni bir C ++ 11 özelliğidir .
Bu, işlevin derleyici tarafından üretilen sürümünü kullanmak istediğiniz anlamına gelir, bu nedenle bir gövde belirtmeniz gerekmez.
Ayrıca kullanabilirsiniz = delete
bunu belirtmek için değil derleyici otomatik olarak bu işlevi oluşturmak istiyorum.
Move yapıcıları ve move atama operatörlerinin tanıtılmasıyla, yapıcıların, yıkıcıların ve atama operatörlerinin otomatik sürümlerinin üretilmesine ilişkin kurallar oldukça karmaşık hale gelmiştir. Kuralların hatırlanması gerekmediğinden işleri kullanmak = default
ve = delete
kolaylaştırır: sadece ne olmasını istediğinizi söylersiniz.
= delete
daha güçlüdür: Bu, aşırı yük çözünürlüğünde yer almasına rağmen, bu işlevi kullanmak yasaktır.
Bu, derleyiciye ilgili yapıcı veya atama operatörünün varsayılan sürümünü, yani her üye için kopyalama veya taşıma eylemini gerçekleştiren varsayılan sürümünü oluşturmasını söyleyen yeni bir C ++ 0x özelliğidir. Bu yararlıdır, çünkü kopya oluşturucu her zaman varsayılan olarak üretilmez (örneğin, özel bir yıkıcıya sahipseniz), kopya kurucudan farklı olarak (ve atama için de aynı şekilde), ancak yazmak için önemsiz bir şey yoksa, derleyici her seferinde kendiniz heceleyerek halledin.
Ayrıca, başka bir varsayılan olmayan kurucu sağlarsanız varsayılan bir kurucu oluşturulmayacağına dikkat edin. Hala varsayılan kurucuyu da istiyorsanız, bu sözdizimini kullanarak derleyicinin bir tane oluşturmasını sağlayabilirsiniz.
Başka bir kullanım durumu olarak, bir kopya oluşturucunun dolaylı olarak oluşturulmayacağı birkaç durum vardır (örneğin, özel bir hareket kurucu sağlarsanız). Hala varsayılan sürümü istiyorsanız, bu sözdizimiyle isteyebilirsiniz.
Ayrıntılar için standardın Bölüm 12.8'ine bakın.
operator new/new[]
, operator delete/delete[]
ve bunların aşırı yükler.
C ++ 11'de yeni, buraya bakın . Bir kurucu tanımladıysanız, ancak diğerleri için varsayılanları kullanmak istiyorsanız oldukça yararlı olabilir. C ++ 11 öncesi, varsayılanlara eşdeğer olsalar bile, bir kez tanımladıktan sonra tüm kurucuları tanımlamanız gerekir.
Ayrıca bazı durumlarda kullanıcı tanım varsayılan kurucu sağlamak imkansız olduğunu unutmayın davranacağını hem alt alta sentezlenmiş derleyici aynı varsayılan ve değer başlatma. default
bu davranışı geri almanızı sağlar.
C ++ 17 N4659 standart taslak
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Açık olarak varsayılan işlevler":
1 Formun bir işlev tanımı:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
açıkça varsayılan bir tanım olarak adlandırılır. Açıkça varsayılan olarak ayarlanmış bir işlev
(1.1) - özel üye fonksiyonu olmak,
. üye işlevinin sınıfının adı) örtük olarak bildirilmiş gibi ve
(1.3) - varsayılan bağımsız değişkenlere sahip değil.
2 Silinmiş olarak tanımlanmayan açıkça varsayılan bir işlev, yalnızca örtük olarak constexpr olarak bildirilmişse constexpr olarak bildirilebilir. Bir işlev ilk bildiriminde açıkça varsayılan olarak ayarlanmışsa, örtülü bildirimin olması durumunda dolaylı olarak constexpr olarak kabul edilir.
3 Açık bir şekilde varsayılan olarak ayarlanan bir işlev, örtülü bildirimle (18.4) aynı istisna belirtimini üretmeyen bir istisna belirteci ile bildirilirse,
(3.1) - işlev ilk bildiriminde açıkça varsayılan olarak ayarlanmışsa, silinmiş olarak tanımlanır;
(3.2) - aksi takdirde program kötü biçimlendirilir.
4 [Örnek:
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
- son örnek]
5 Açık olarak varsayılan işlevler ve örtük olarak bildirilen işlevler topluca varsayılan işlevler olarak adlandırılır ve uygulama, bunlar için silinmiş olarak tanımlanmaları anlamına gelebilecek örtük tanımlamalar (15.1 15.4, 15.8) sağlayacaktır. Bir işlev, kullanıcı tarafından bildirilmişse ve ilk bildiriminde açıkça varsayılan olarak veya silinmemişse kullanıcı tarafından sağlanır. Kullanıcı tarafından sağlanan açıkça varsayılan bir işlev (yani, ilk bildiriminden sonra açıkça varsayılan), açıkça varsayılan olduğu noktada tanımlanır; böyle bir işlev örtük olarak silinmiş olarak tanımlanırsa, program kötü biçimlendirilir. [Not: Bir işlevi ilk bildiriminden sonra varsayılan olarak varsayılan olarak bildirmek, gelişen kod tabanına istikrarlı bir ikili arabirim sağlarken verimli yürütme ve özlü tanımlama sağlayabilir. - son not]
6 [Örnek:
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
- son örnek]
O zaman soru elbette hangi fonksiyonların dolaylı olarak beyan edilebileceği ve ne zaman gerçekleştiği, ki ben de açıkladım: