2015-05-13 18 views
5

Örneğin işe yaradığından eminim.Bir unique_ptr öğesinin ham bir işaretçisini alıp sıfırlamayı kullanırsam, ham işaretçinin hala geçerli olduğunu mu garanti ettim?

int foo = 51; 
int* bar = &foo; 
foo = 3; 

Yani bar hala geçerlidir ve *bar == 3. biz söylersek

Peki

std::unique_ptr<int> foo(new int(51)); // should probably use make_unique 
int* bar = foo.get(); 
foo.reset(new int(3)); 

Ben *bar == 3 garanti muyum? Yoksa referans çubuğuna devam ederek tanımlanmamış davranışlara neden oluyorum?

cevap

8

Hayır, hiç değil. unique_ptr tarafından yönetilen ham işaretçi reset tarafından değiştirildiği için, tanımlanmamış davranış alırsınız. Aslında, unique_ptr yönetilen işaretçi siler ve yenisini reallocates, böylece eski işaretçi artık geçerli değil eski adrese işaret ederek devam edecektir. Kodunuz bu eşdeğerdir:

#include <iostream> 

int main() 
{ 
    int* managed = new int(51); // equivalent to unique_ptr(new int(51)); 
    int* bar = managed; // equivalent of unique_ptr::get 
    delete managed; managed = new int(3); // equivalent to unique_ptr::reset(new int(3)) 
    std::cout << *bar << std::endl; // Wrong!!! Undefined behaviour, bar is dangling! 
} 

İlk Kod parçacığı orada herhangi adresini değiştirerek olmadığı için elbette işaretçiyi kaldırma alacak böylece, sadece, işaretçi noktaları değişkeni değişiyor, gerçekten doğru olduğunu güncelleştirilmiş değer.

7

Bir unique_ptr sıfırlamak Hayır, eğer o sahibi olan işaretçi silecektir.

Sen yapabilirsiniz:

int* bar = foo.release(); 

Bu, pointer sahipliğini vazgeçmek ve bunu iade etmek foo neden olur.

+0

ben 'çubuk = foo.get()' kurmak ve daha sonra ben foo değiştirmek için gidiyorum karar verirseniz, ben sadece çağrı 'foo.release()' ve çubuk açık ataması olmadan sahipliğini varsayalım ki? Gerçekten bir kullanım vakası düşünemiyorum, ama bu doğru çalışacaksa merak ediyorum. – wrhall

+1

@wrhall: Hayır, yapamazsınız. Bu muazzam güvensiz olurdu. Unique_ptr * her zaman * işaretçinin sahibidir. Bu tek amaç. Bunu yalnızca, asla aramamanız gereken korkunç bir işlev olan 'release()' kullanarak engelleyebilirsiniz. – Puppy

+0

@Puppy, kötü bir uygulama olsa bile teknik olarak doğru mu? Belgelere bakıldığında, 'release() '* Eğer yönetilen nesnenin sahipliğini varsa serbest bırakır. çağrısından sonra 'nullptr' döner) (get * Yani serbest bırakma()' gerçekten 'yapar dönüş managed_ptr' bana bakıyor;. 've "non-yönetme" olarak' unique_ptr' işaretler, böylece gelecekteki 'almak()' dönüş nullptr. Bunun gerçekten böyle olup olmadığını biliyor musun? – vsoftco