2017-05-09 48 views
6

から '変更可能な' エミュレート:C - 私はこのようなC構造を持つC++

struct my_struct { 
    int i; 
    double d; 
    struct expensive_type * t; 
}; 

この構造体のインスタンスは次のように作成され、初期化されます。

struct my_struct * my_new(int i , double d) 
{ 
    struct my_struct * s = malloc(sizeof * s); 
    s->i = i; 
    s->d = d; 
    s->t = NULL; 
    return s; 
} 

struct expensive_type * tメンバーの計算はかなりあります高価であり、必要ではない可能性があります。それはNULLに初期化され、後で必要に応じて計算されます:

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; 
} 
私は struct expensive_type *部材に mutableを使用していたCで

、それはローカルでのconstを離れてキャストC、すなわちに似た何かを達成することが可能である:

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

}

または署名でconstを削除して私の唯一の標準に準拠した代替品ですか?

+3

Cの中に '変更可能なもの 'やそれに近いものはありません。 – DyZ

+1

はい、' const'を削除するか、UBを被る必要があります。ニース投稿。良い答えはCの仕様を引用するでしょう。 – chux

+0

なぜコードは 'my_get_expensive(const struct my_struct * s)'に 'const'を必要としますか?おそらく、その目標は別の方法で満足できるでしょうか? – chux

答えて

2

あなたは、(1)再構築あなたのコードができ、間接のレイヤーを追加します。

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; 
} 

my_structの作成

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 
}; 

は間接に使用するハンドル/追加のポインタを作成する必要がありますtargetメンバー(最初に計算されると高価なデータを指します)は、最初にNULLに設定されています。

は、アクセスする(したがって、おそらくの遅延計算)そのmy_structのないデータメンバが変更されていないため、高価なデータメンバは、さえconst資格my_structとが可能である:変更

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; 
} 

唯一のものです*(ptr->handle)struct expensive_handleのデータメンバー。 const修飾されていないもの(handleという名前のポインタだけです)。

テスト(Live on ideone):

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

(1)これは合理的であるか、リソースの完全な廃棄物(プログラマと計算の両方が)しかし、あなたのダミーの例から決定することができないかどうか。

+0

有権者の皆様、私の回答のどの部分を改善すべきか説明してください。 –

+0

ありがとうございます - 私の(本当の...)ケースでは間接指導は確かに価値があります! – user422005

関連する問題