2012-04-18 36 views
1

給定一個模板類,像這樣:是否有可能聲明不佔用內存的成員變量?

template <typename T> 
class C 
{ 
T member; 
//... some other members that are not of interest here 
}; 

有什麼類型,我可以爲T給防止member採取了不必要的內存? 起初void彈出我的腦海,但我知道你不能聲明void變量。

備註
當然這個例子被簡化了。背景是一個持有一些信息的類,但可以獲得用戶添加的附加信息。當用戶不想添加額外信息時,應該可以將它們排除在外。所以基本上如果用戶想要存儲額外的數據,他將構造C<MyAdditionalData>,但是如果他不這樣做,它應該像C<NoData>,並且不會有數據。當然,我可以寫一些模板專業,但我不喜歡把所有東西都寫兩遍。

編輯
好吧,我發現一個空類是最接近我可以得到(仍然會消耗1個字節,甚至4/8,因爲對齊),到目前爲止,所以我現在的問題是: 有已經有一些標準的空類,我應該用它來使我的代碼更具可讀性?

+0

如果您不想要,您不必擁有會員。 'class C {};' – 2012-04-18 11:12:37

+0

@BoPersson:當然,但我確實希望模板有可能存儲成員。 – Nobody 2012-04-18 11:13:17

+0

也許你應該告訴我們你的目標是什麼,而不是你如何努力實現它。如果不知道自己想要達到什麼目的,很難得到五條建議(因爲如果你需要它,你不能讓'成員'佔用內存......) – Grizzly 2012-04-18 11:14:28

回答

2

對於數據成員no,因爲對象從不是大小零,並且數據成員沒有退出子句。

然而,基類子對象可以有大小爲零,如果它是空的。因此:

template <typename T> 
struct Member { 
    T member; 
}; 

template <> 
struct Member<void> { 
}; 

template <typename T> 
class C : private Member<T> 
{ 
//... some other members that are not of interest here 
}; 

應該工作,我認爲。但是你可能會忽略C<void>::member不存在的事實,所以使用它的任何成員函數都不會編譯爲C<void>,包括構造函數。

如果用戶希望存儲更多的數據,他將構建 C<MyAdditionalData>

爲什麼不C非模板類沒有額外數據成員,如果用戶想增加數據成員,使用C作爲基類?記得給C受保護的析構函數 - 每一個基類應該有或者是受保護的析構函數或虛析構函數,但因爲你的C模板類沒有虛析構函數那麼就沒有必要非模板版本是虛擬要麼。

沿着這些線路,你可以這樣做:

class CNoData 
{ 
//... some other members that are not of interest here 
}; 

template <typename T> 
class CWithData<T> : CNoData 
{ 
T member 
// have to duplicate constructors, unfortunately. 
}; 

,如果你真的需要它,添加類型特點:

template <typename T> 
struct C { 
    typedef CWithData<T> type; 
}; 

template <> 
struct C<void> { 
    typedef CNoData type; 
}; 

然後在那裏你會寫C<MyAdditionalData>,現在你寫CWithData<MyAdditionalData> ,你會寫C<some_type_that_might_be_void>你寫typename C<some_type_that_might_be_void>::type

+0

+1我認爲這非常解決了這個問題。起初我害怕額外的運行時間開銷,但後來我意識到沒有虛函數,所以在編譯時所有東西都應該被整齊地解決。不得不復制構造函數是一個小的負數,但幸運的是,它們是這個類的一小部分。回顧過去,我想知道爲什麼這不會出現在我的腦海裏,因爲它更清晰,即使在實施這個問題的邏輯中也是如此。 – Nobody 2012-04-18 13:11:49

3

好吧,我發現一個空類是最接近我能得到這麼遠,所以現在我的問題是:是否已有一些標準空類,我應該使用這使我的代碼更易讀?

號您可以定義一個自己:

struct standard_empty_class {}; 

使用它。

如果用戶希望存儲更多的資料,因此基本上他將構建C<MyAdditionalData>,但如果他不應該是這樣C<NoData>會有任何數據。

我不明白這一點。如果用戶不想存儲任何數據,那麼爲什麼即使你需要一個類,仍然需要編寫C<NoData>?忘記那個案子吧。沒有數據意味着沒有課。它不解決嗎?

+0

好的,謝謝你的信息。我怕是沒有的,所以現在我要考慮一個地方,把這個的,所以它是每個用戶(防止數百個新的空類新興:) – Nobody 2012-04-18 11:23:21

+0

@Nobody可見:在你的效用定義這個類頭。 :-) – Nawaz 2012-04-18 11:26:03

+0

關於你的第二個評論:基本類存儲圖形拓撲。用戶添加的數據是圖形本身不需要的節點/邊的附加信息。如果用戶只想存儲沒有關於節點/邊的附加信息的圖,那麼最好不浪費無用的成員(附加數據)。 – Nobody 2012-04-18 11:28:04

2

我不認爲這是可能的。其實,這是另一種方式。實例化時,即使是空類也會佔用內存(一個字節),因此程序在實例之間可能會有所不同。也就是說

class A { 
}; 

A a, b; // vars of type A 

然後ab必須採取一些內存,使你的程序可以參考它們,例如,if (a == b)。如果他們不使用內存,你不能這樣做。

+0

那麼問題不是關於實例,而是如何給編譯器提示甚至不創建該字段。不幸的是,這似乎不可能,但我想確定,所以這就是爲什麼我問 – Nobody 2012-04-18 11:25:58

5

專門爲您的模板類NoData類型,並沒有定義在這個專業化的成員。

template <class T> 
class C { 
    T member; 
... 
}; 

template<> 
class C<NoData> { 
    // Do not declare that member 
}; 
+0

這是我想到的事情之一,但我如何避免在專業化中再次定義每個功能?在這個例子中我沒有包括它們,但是大約有10個函數,它們很長。 – Nobody 2012-04-18 12:59:09

+1

宏或繼承。如果你使用繼承,你可以讓模板繼承普通的基類,所以基類本身就是無參數的解決方案。 – 2012-04-18 14:03:03

+0

@沒有人會繼承。不要忘記雙向繼承是允許的,它們提供了不同的可能性。 – enobayram 2012-04-18 14:17:40

1

正如你所說的,該模板已經包含了一些其他數據。它具有虛擬方法,那麼這又是一個成員。

添加一個額外的成員是一個非常小的開銷,可以簡單地忽略,所以我只用C.(或者有其他成員比排列更小的甚至焦炭)

使用的typedef更清晰:

typedef C<int> CEmptyGraphNode; 
+0

哦,實際上enobayram的解決方案可以創造奇蹟,但我仍然保留typedef:) – 2012-04-18 12:12:51

相關問題