c++的模板可以幫助我們編寫適合不同型別的模板類,給**的復用性提供了極大的方便。近來寫了乙個涉及單例的c++模板類,簡化下來可以歸結為以下的**:
1
2
3
4
5
6
7
8
9
10
11
template
<
typename
t>
class
singleton
};
那麼如果希望對某個work horse類,比如叫做foo,定義乙個singleton,就會很容易啦: 1
foo* foo = singleton::getinstance();
注意這裡不需要自己釋放foo,因為它不是new出來的。
如果**被編譯成「乙個」so(dll)或可執行檔案,這裡的singleton得到的物件卻是是單例的,也就是說,某一種型別得到的物件位址是確定的。
但是,如果同乙個型別的單例在不同的so(dll,可執行檔案)中使用,那麼得到的同乙個型別的單例物件,其位址也是不一樣的。比如
libfoo.so檔案中的如下**:
1
2
foo* foo = singleton::getinstance();
std::type_info footype =
typeid
(singleton);
和libbar.so中的另一端**: 1
2
3
foo* bar = singleton::getinstance();
std::type_info bartype =
typeid
(singleton);
其中foo和bar的位址是不同的!他們並不是真正的單例。
為什麼呢?原因是模板是編譯的時候例項化成「真正的類」的,而在兩個不同的so編譯生成的過程中,編譯器進行了兩個不同的例項化過程,他們被例項化成了不同的類。也不是完全不同,但有部分是不同的。
比如,對上述兩個so,如果去測試兩個singleton型別是否為同一型別(rtti):
1
if
(footype == bartype)
那麼該測試會返回false。但是,如果測試兩個型別的名字是否相等: 1
if
(
strcmp
(footype.name(), bartype.name()) == 0)
該測試則會返回true。
這說明,兩個型別雖然type_info不同,但名字卻是相同的。
在google上搜了一下相關的資訊,發現這確實是乙個難題。因此,用模板來實現單例,是無法跨so的。當然,這裡不是真正用模板來實現單例,只是用這個例子來演示模板的rtti特性。
設計模式 再嚴謹的單例也盡量不要使用
設計模式學習 注意 大多數的開發者都認同使用全域性可變的狀態是不好的行為。太多狀態使得程式難以理解,難以除錯。不管什麼情況下,我們都應該慎重考慮一下是否必須使用單例。單例應該只用來儲存全域性的狀態,並且不能和任何作用域綁 定。如果這些狀態的作用域比乙個完整的應用程式的生命週期要短,那麼這個狀態就不應...
EXE中使用DLL的模板類
模板類是乙個編譯鏈結期間才例項化的類。只有用到才例項化。標準沒有支援對模板類的匯出,從另外一種意義上來說,模板類的實現全部放在標頭檔案中,也就不需要匯出了。但是對於一些特別情況。模板類中有靜態變數和函式。這個時候dll中使用的,以及和其他鏈結這個dll的模組他們是使用的兩份拷貝。比如,在dll中這樣...
另人厭煩的執行緒安全單例以及不要使用雙檢測
群裡熱烈的討論了執行緒安全的單例 一路從volitile扯到彙編,從 到 真是夠了 首先volitile 跟多執行緒沒直接的關係,或許有些特定情況下會用到 至於spincout之類的實現,內部使用了volitile,這類就不多說了,有興趣的可以自己看實現 千萬別使用下面 不要使用雙檢測,不要使用雙檢...