2017-05-09 52 views
6

gelen taklit 'kesilebilir' pahalı ve gerekli olmayabilir - sadece NULL için başlatılmış - ve daha sonra istek üzerine hesaplanır:Cı Böyle bir Cı yapıya sahip olan, C++

const struct expensive_type * my_get_expensive(const struct my_struct * s) 
{ 
    if (!s->t) 
     s->t = my_expensive_alloc(s->i , s->d); 
    return s->t; 
} 
C

++ ben struct expensive_type * üyesinde mutable kullanılmış olurdu, bu mümkün lokal olarak const uzak döküm yani C benzer bir şey, elde etmektir:

{ 
    struct my_struct * mutable_s = (struct my_struct*) s; 
    mutable_s->t = ...; 

}

Ya imzasında const kaldırıyor tek standart uyumlu alternatifim? Bir my_struct ek işaretçi oluşturmalısınız oluşturma

struct expensive; // Forward declaration, ignore 
// One could also use a struct expensive * (a pointer) instead 
// of this structure. IMO giving it a name is the better option. 
struct expensive_handle { 
    struct expensive * target; 
}; 

// Store the simple data members as usual, store a pointer to a 
// handle (pointer) to the expensive ones 
struct my_struct { 
    int simple; 
    struct expensive_handle * handle; 
}; 

struct expensive { 
    int content; // whatever 
}; 

/dolaylama için kullanılan tutma sapı:

struct my_struct * new() { 
    struct my_struct * data = malloc(sizeof(*data)); 
    // Error handling please 
    // Set simple data members 
    data->handle = malloc(sizeof(*(data->handle))); 
    // Error handling please 
    data->handle->target = NULL; 
    return data; 
} 

+3

C. 'de' değişebilir 'veya ona yakın bir şey yoktur. – DyZ

+1

Evet,' const 'öğesini kaldırmalı veya UB'ye zarar vermelidir. Güzel yazı olsa da. İyi bir cevap C spec. – chux

+0

Neden kod, 'my_get_expensive (const struct my_struct * s)' içinde 'const'' ye ihtiyaç duyar? Belki de bu hedef başka bir şekilde karşılanabilir mi? – chux

cevap

2

Sen (1) yeniden yapılandırılması kodunuzu ve dolaylama katmanı ekleyebilirsiniz target üyesi (hesaplandıktan sonra pahalı verilere işaret edecek) başlangıçta NULL olarak ayarlanmıştır. bu my_struct arasında herhangi bir veri elemanı değiştiğinden

Erişim (ve böylece olasılıkla yavaş hesaplama) pahalı veri üyeleri, hatta const kalifiye my_struct ile mümkün olmaktadır:

int get_expensive(struct my_struct const * ptr) { 
    if (ptr->handle->target == NULL) { 
    ptr->handle->target = malloc(sizeof(struct expensive)); 
    // Error handling please 
    puts("A hell of a computation just happened!"); 
    ptr->handle->target->content = 42; // WOO 
    } 
    return ptr->handle->target->content; 
} 

değiştiren tek şey *(ptr->handle) veri üyesi, bir struct expensive_handle. Hangi const kalifiye değil (sadece handle isimli ismidir).

Testi (Live on ideone):

int main(void) { 
    struct my_struct * p = new(); 
    printf("%d\n", get_expensive(p)); 
    printf("%d\n", get_expensive(p)); 
} 

(1) Bu da, makul veya kukla örnekten karar alınamaz kaynakların tam kaybı (programcı ve hesaplama ikisi) olmadığı.

+0

Sevgili oy veren, lütfen cevabımın hangi bölümlerinin geliştirileceğini açıklayın. –

+0

Teşekkür ederim - benim (gerçek ...) davamda kesinlikle buna değer! – user422005