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.