C ++ 11'de auto_ptr kullanımdan kaldırma için tasarım değişiklikleri nasıl ele alınır?


12

C ++ 11 (yani -std=c++11) altında bir kitaplığı test ediyoruz . Kütüphane auto_ptrşunları kullanır :

Foo* GetFoo()
{
    autoptr<Foo> ptr(new Foo);

    // Initialize Foo
    ptr->Initialize(...);

    // Now configure remaining attributes
    ptr->SomeSetting(...);

    return ptr.release();
}

C ++ 11 kullanımdan kaldırıldı auto_ptr, bu yüzden ondan uzaklaşmak istiyoruz.

Ancak, kod hem C ++ 03 hem de C ++ 11'i destekler, bu yüzden yankılanma kadar basit değildir auto_ptr. Ayrıca kütüphanenin dış bağımlılıkları olmadığını belirtmek gerekir. C ++ 03 kullanır; ve Autotools, Cmake, Boost, ... kullanmaz.

auto_ptrC ++ 03 ile uyumluluğu korurken C ++ 11'den uzaklaşmak için tasarım değişikliklerini nasıl ele almalıyız ?


Olan var auto_ptrscoped (yani std::auto_ptr), olmaları gereken veya akıllı işaretçi başka ad elde edilebilir mi?
Niall

Bir yana, Foo::Initializeiçine katlanmak isteyebilirsiniz Foo::Foo.
MSalters

1
@MSalters - evet, bu her zaman hafifçe rahatsız hissettiğim şeylerden biri oldu. Kütüphane 1990'larda tasarlandı ve bence tasarım MFC'ye benziyordu. Yani, daha düşük seviye C ++ yapısı ve sonra "daha yüksek seviye" bir nesne yapısı vardı. Bence özellik takas olarak kullanıldığından, sınıfların 6 veya 12 farklı kurucuları yoktur. (Bu noktada, yaptığım şey geçti ve POD türlerinin üye değişkenlerinin C ++ kurucularında aklı başında varsayılanlara başlatılmasını sağladı).

Yanıtlar:


13

En bakımdan std::unique_ptriçin (ama daha güvenli) yerine düşüş olması için yapıldı std::auto_ptrkullanım ya kod yönlendiren (varsa) (sorduğunuz gibi) kod değişiklikleri dışında gerekli yüzden çok az olmalıdır, unique_ptrya da auto_ptr.

Bunu yapmanın birkaç yolu vardır (ve her biri kendi liste ödünçleriyle birlikte gelir). Verilen kod örneği göz önüne alındığında, ilk iki seçenekten birini tercih ederim .

seçenek 1

#if __cplusplus >= 201103L
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif

tradeoffs;

  • Sen tanıtmak auto_ptrküresel ad alanına; bunu kendi "özel" ad alanınız olarak tanımlayarak hafifletebilirsiniz.
  • C ++ 17'ye geçtikten sonra ( auto_ptrtamamen kaldırılacağına inanıyorum ) daha kolay arama ve değiştirme yapabilirsiniz

seçenek 2

template <typename T>
struct my_ptr {
    #if __cplusplus >= 201103L
    typedef std::unique_ptr<T> ptr;
    #else
    typedef std::auto_ptr<T> ptr;
    #endif
};

tradeoffs;

  • Muhtemelen çalışmak daha hantal auto_ptr, koddaki tüm mevcut ihtiyaç gibi bir şeye değiştimy_ptr<T>::ptr
  • Daha iyi güvenlik, adların global ad alanına girmemesi

Seçenek 3

Biraz tartışmalı, ancak stdbir üs olarak bir sınıfa sahip olma uyarılarına katlanmak için hazırsanız

#if __cplusplus >= 201103L
template <typename T>
using my_ptr = std::unique_ptr<T>;
#else
template <typename T>
class my_ptr : public std::auto_ptr<T> {
  // implement the constructors for easier use
  // in particular
  explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {}
};
#endif

tradeoffs;

  • Sanal bir tabanın (özellikle sanal olmayan yıkıcı) beklendiği kalıtsal sınıfı kullanmaya çalışmayın. Bu durumun bir sorun olması gerektiği değil - ama bunun farkında olun
  • Yine, kod değişir
  • Potansiyel ad alanı uyuşmazlıkları - her şey işaretçi sınıfının başlangıçta nasıl kullanıldığına bağlıdır

Seçenek 4

İşaretçileri yeni bir sınıfa sarın ve gerekli işlevleri üyeye toplayın

template <typename T>
class my_ptr { // could even use auto_ptr name?
  #if __cplusplus >= 201103L
  std::unique_ptr<T> ptr_;
  #else
  std::auto_ptr<T> ptr_;
  #endif

  // implement functions required...
  T* release() { return ptr_.release(); }
};

tradeoffs;

  • Gerçekten istediğiniz tek şey, uygulamaları "değiştirmek"

Çok iyi bir cevap. Aslında biraz araştırdım ve denediğim testlerden en az üçünü aldın. (Eksik olan şey OS X ve Clang'a özgü şeylerdir. OS X bir ayıdır çünkü hala C ++ 03 için TR1 ad alanını kullanıyor ve bu yöntemi kullanarak bir şeyler eklemeniz gerekiyor: Ad alanında 'unique_ptr' adında bir tür yok LLVM / Clang altında derlerken 'std' ).

@jww. OS X kullanıyorum (XCode 6.4 ve Apple LLVM sürüm 6.1.0 (clang-602.0.53) (LLVM 3.6.0svn tabanlı)) ve tr1ad alanı dışında C ++ 03/11 karışımı ile ilgili sorun yok orada olmak daha uzun (libc ++ değil libc ++ kullanıyorum). Tr1'in normatif olmadığını biliyorum, ancak taslakta (burada) dosyaların hiçbir yerde olması gerektiğini bulamıyorum <tr1/...>, sadece isim alanında başlık <memory>vb tr1.
Niall

@jww. Belirli bir derleyici, kütüphane ve hedef cihaz karışımı verildiğini düşünüyorum - birkaç el standı daha yapmanız gerekebilir. Diğer, OS X'te clang ve libc ++ 'a geçmeyi düşünün. Açıkçası ben libc ++ OS X yeni "yerli" C ++ kitaplığı olarak kabul - Ben varsayılan olarak. Clang / Apple ilişkisinin tarihinin ve OS X'teki GCC araçlarının güncel (kütüphane) veya sadece kaldırıldığını (GCC'nin zaten clang için ince bir saplama olduğunu bildiğim kadarıyla) bu iddiaları destekleyemiyorum ).
Niall

"Else, OS X'te clang ve libc ++ 'a geçmeyi düşünün ..." - evet, sana katılıyorum. Ancak, kullanıcıların bu seçimi yapmasına izin vermek ve onları zorlamamak istiyoruz. (Belirlediklerinde (veya yokken) örtük olarak seçim yaparlar CXX=...).

İşte OS X 10.7 ve 10.8 bana bu kadar sorun neden olan durum: c++ -v -std=c++11 -x c++ - < /dev/null. Ben grep'datıldığı dizinleri içerir ve bunlar yok değil bulunmaktadır unique_ptr.

0

Seçenek 5: Doğrudan takma ad.

#if __cplusplus >= 201103L
template<typename T> 
using MyPtr = std::unique_ptr<T>;
#else 
#define MyPtr std::auto_ptr
#endif 

tradeoffs:

  1. Daha yeni bir dil olan AKA C ++ 11 ve sonraki sürümler için takma ad türünüz doğru akıllı işaretçiyle eşleşir. Aslında std :: auto_ptr'e özgü API'lara bağlı olan herhangi bir kullanıcı kodu derleyici tarafından işaretlenecektir, bu da gerçekten düzeltileceğini garanti eder.

  2. Eski c ++ 03 modunda, diğer ad bir makrodur. Bu brüttür, ancak ortaya çıkan sözdizimi MyPtr<T>, kodun geri kalanında C ++ 11 durumu ile aynı olacaktır.

  3. Bunu MyPtrayarlamak için tüm auto_ptr değişkenlerinizi bulup değiştirmeniz gerekir .


1
Bunun neye atıfta bulunduğu çok açık değil (ve ifade edildiği gibi, bu bir soru değil).
otofaj

1
@autophage Bir cevap olduğuna inanıyorum ... bu yüzden muhtemelen bir soru değil.
Kain0_0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.