2016-04-03 24 views
0

Aşağıdaki kodu düşünün:İşaretçiyi değiştirmenin daha idiomatik bir yolu var mı?

#include <memory> 
#include <stdio.h> 
#include <stdexcept> 

class Foo { 
    public: 
     Foo(int n) { val =n; printf("Hi %d\n", val); }; 
     ~Foo() { printf("Bye %d\n", val); }; 
    private: 
     int val; 
}; 

int main() 
{ 
    std::shared_ptr<Foo> p = nullptr; // I don't know what I want yet 
    p = std::make_shared<Foo>(1); // OK, I've decided 

    // I've changed my mind, it needs to be something else 
    p = nullptr; 
    p = std::make_shared<Foo>(2); 

    return 0; 
} 

Onun çıkışı:

Hi 1 
Bye 1 
Hi 2 
Bye 2 

Bu yapmacık bir örnek. Foo oldukça ilgi çekicidir. Sadece ömrü ile ilgili bilgi yazdırır.

Kodun arkasındaki mantık şudur: p bildiriyorum, ancak başlangıçta ne gerektiğini bilmiyorum. Sonra ne olduğunu bildiğime karar veririm: 1. değeri almalıdır. Gerçek kodumda bu değer uzun sürebilir.

Bir süre sonra, bunun 1 olmamasına, 2 olması gerektiğine ben karar veririm. Daha önce ne olursa olsun, imha edilmeli ve başka bir şeyle değiştirilmelidir.

Şimdiye kadar, benim anlayışım yukarıdaki kodun bellek yönetimi açısından iyi ve istisnalar altında sağlam olmasıdır.

demenin daha deyimsel yolu var mı:

p = nullptr; 
p = std::make_shared<Foo>(2); 

elimden önce sahip tahrip edilmesi gerektiğini söylemek istiyorum çünkü ben sadece son satırı yazamazsınız.

+1

_ ile yeni paylaşır. _ "Son satırı yazamam, çünkü daha önce elimden gelenin daha önce yok edilmesini istiyorum." _ Sadece ikinci çizgiyi düşünmenizi sağlayan şey nedir? 'nullptr' atamaktan başka eski değerin yıkımını tetiklemez mi? –

+1

Çünkü "p = nullptr" konusunu açıkladığım zaman, Hi 1, Merhaba 2, Hoşçakal 1, Hoşçakal 2. çıkışını elde ediyorum. IOW, ilk ödev çok uzun sürüyor. – blippy

+0

Bunun nedeni, ** 2 ** nesnesinin, atamadan önce "p" olarak oluşturulmasıdır. Eğer ** 1 ** nesnesine gerçekten ihtiyaç duyarsanız, ** 2 ** oluşturulduğunda ** 2 ** oluşturmadan önce 'p'' nullptr '' i ayarlamanız gerekir. Bunun için bir deyim yoktur, çünkü bu zor bir gerekliliktir. – Motti

cevap

2

Sadece imlecin atanması, önceki değere ihtiyacınız olmadığını bildirmek için yeterlidir. paylaşılan işaretçisi olduğundan ve başka sahiplerine sahip olabileceğinden, imha edilmesi gerekip gerekmediğini söylemezsiniz.

Benim görüşüme göre atama yeterlidir ancak shared_ptr::reset()'u kullanmayı tercih edebilirsiniz.

+1

'reset()' için bir kullanım durumu gibi görünüyor, çünkü denetim bloğu ve 'Foo 'örneğinin bir ayrılmasına neden olduğundan daha az verimlidir. –

+0

@RichardHodges, Kabul ediyorum, [olmadığı zaman] (https://lanzkron.wordpress.com/2012/04/22/make_shared-almost-a-silver-bullet/). – Motti

+0

Ama hadi gerçekçi olalım. Bellek lokasyonu neredeyse her zaman biraz fazladan bir hafızada tuttuğumuzdan daha önemlidir.shared_ptr kopyalama veya zayıf_ptr'yi kilitleme ortak bir işlemdir ve * hemen hemen her zaman * sonra pointee nesnesinin kendisine erişir. Bu durumda, make_shared durumunda, nesnenin başlangıcı (sıcak parça) zaten sizi bekleyen veri önbelleğinde. –

1

Eğer deyimsel (iyi!) Istemek için, en deyimsel olalım:

#include <memory> 
#include <stdexcept> 
#include <iostream> 

class Foo { 
public: 
    Foo(int n) 
    : val(n) 
    { 
     std::cout << "Hi " << val << "\n"; 
    }; 
    ~Foo() { 
     std::cout << "bye " << val << "\n"; 
    }; 
private: 
    int val; 
}; 

int main() 
{ 
    auto p = std::shared_ptr<Foo>(); // I don't know what I want yet 
    p = std::make_shared<Foo>(1); // OK, I've decided 

    // I've changed my mind, it needs to be something else 
    p = std::make_shared<Foo>(2); 

    return 0; 
} 
1

burada

p = std::make_shared<Foo>(2); 

Bu hat yapmam gereken başka bir şey yok imiş p önceki nesneyi yok eder Bu nesneye son başvuru. Daha sonra yeni paylaşım

İlgili konular