青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-90  評論-947  文章-0  trackbacks-0

打算先把基礎的東西組織起來,作為一個“大庫”(見上一篇《小庫還是大庫?》)。然后填加各個實用功能,作為一個個小庫或者大庫,過段時間再想辦法組織整理了。

首先是類型系統,我想來想去,覺得還是必須整理一下,尤其是 unsigned XXX 寫起來太難看了,可是這又帶來了問題——WinDef.h 把好聽的名字都占去了。然后,我只能在自己的命名空間下這樣來一番了:

xlDef.h
#ifndef __XLDEF_H_44FDC6C3_12F1_4BF3_8F9F_1ABED755E8ED_INCLUDED__
#define __XLDEF_H_44FDC6C3_12F1_4BF3_8F9F_1ABED755E8ED_INCLUDED__


namespace xl
{
   
typedef char CHAR;
   
typedef unsigned char UCHAR;
   
typedef short SHORT;
   
typedef unsigned short USHORT;
   
typedef int INT;
   
typedef unsigned int UINT;
   
typedef long LONG;
   
typedef unsigned long ULONG;
   
typedef long long LONGLONG;
   
typedef unsigned long long ULONGLONG;

   
typedef void VOID;
   
typedef bool BOOLEAN;
   
typedef INT BOOL;

   
typedef UCHAR BYTE;
   
typedef USHORT WORD;
   
typedef ULONG DWORD;
   
typedef ULONGLONG QWORD;

   
const BOOL TRUE = 1;
   
const BOOL FALSE = 0;
   
const VOID *NULL = 0;

   
typedef struct interface;

}
// namespace xl


#endif // #ifndef __XLDEF_H_44FDC6C3_12F1_4BF3_8F9F_1ABED755E8ED_INCLUDED__

但是,問題是,當 using namespace xl 并 #include <Windows.h> 以后,隨手寫一個“DWORD”,就會有歧義了。如果用的時候要寫成 xl::DWORD,那還不如現在就命名成 XL_DWORD 好了……這點仍然在糾結中……路過朋友請給點意見:)

接下來是最基礎一層的組成。我想先把 Array、List、BinaryTree 給實現一下。然后第二層中利用 Array 實現 String,利用 List 搞個 Queue、Stack 什么的,利用 BinaryTree 搞個 Map、Set 之類的。只是數據結構中的“圖”,不知道怎么搞比較方便,如果可能,也可以在第一層實現掉。

不得不考慮的是 iterator 的問題。由于 STL 的 iterator 深入人心,我很想也搞個類似的支持。但是,STL 的 iterator 是可以跨容器的,也就是,可以在 list 的 insert 里填入 vector 的 iterator 作為參數。我不太了解 STL 的具體做法,但是粗看似乎是用模板實現的??墒沁@樣的話,就有一個很大的問題,這個模板參數將是沒有任何約束的,在明明需要 iterator 的參數的位置,我可以隨意填一個別的東西,直到有調用 iterator 的什么方法,編譯器才給出錯誤。這樣,實際上在接口中沒法為使用者提供足夠的信息(或者說,提供語法上的約束)讓他明白這個參數應該是什么。比較好的做法可能是 .Net 的那一套,定義接口 IEnumerator、IEnumerable 等等,然后各個類都去實現這個接口,迭代器也可以只針對接口編寫。但是由于 C++ 中的多態必須用指針表示,那么在參數、返回值(特別是返回值)中,指針的 delete 又給使用帶來了麻煩。于是,似乎需要先有一個完善的智能指針作為基礎才可以。而智能指針,如果要線程安全,又必須有平臺支持,所以似乎智能指針沒法放在這么基礎的位置?!?/p>

繞了好久,也想了好久,始終還是找不到好的辦法。所以,我暫時覺得還是放棄跨容器的 iterator 了,其實說到底,這只是勉強制造的、看似來很精巧、其實不那么完美的東西而已。

Array、List、Tree 暫時設計如下:

xlArray.h
#ifndef __XLARRAY_H_3B18D7E2_B52A_4D57_BE4B_657F9D17320D_INCLUDED__
#define __XLARRAY_H_3B18D7E2_B52A_4D57_BE4B_657F9D17320D_INCLUDED__


#include "xlDef.h"

namespace xl
{

   
template <typename T>
   
class Array
   
{
   
public:
       
Array();
       
Array(const Array<T> &that);
        ~
Array();

   
public:
       
class Iterator
       
{
       
public:
           
Iterator();
           
Iterator(const Array<T> *array);
           
Iterator(Iterator &that);

       
private:
           
array<T> *array;
           
UINT current;
           
BOOLEAN bof;
           
BOOLEAN eof;

       
public:
           
T &operator * ();
           
T *operator -> ();

       
public:
           
Iterator &operator = (Iterator &that);
           
BOOLEAN operator == (Iterator &that);
           
BOOLEAN operator != (Iterator &that);

       
public:
           
Iterator operator ++ ();
           
Iterator operator ++ (int);
           
Iterator operator -- ();
           
Iterator operator -- (int);
        };

   
public:
       
Iterator Bof();
       
Iterator Begin();
       
Iterator End();
       
Iterator Eof();

   
public:
       
Array<T> &operator=(const Array<T> &that);
       
BOOLEAN operator==(const Array<T> &that) const;
       
BOOLEAN operator!=(const Array<T> &that) const;

   
public:
       
T &operator[](UINT index);
       
const T &operator[](UINT index) const;

   
public:
       
BOOLEAN Empty();
       
UINT Count();

   
public:
       
VOID PushFront(const T &tValue);
       
VOID PushBack(const T &tValue);
       
VOID PopFront();
       
VOID PopBack();
       
VOID Insert(const Iterator &beforeWhich, const T &value);
       
VOID Insert(const Iterator &beforeWhich, const Iterator &firstToInsert, const Iterator &NextOfLastToInsert);
       
Iterator Delete(const Iterator &which);
       
Iterator Delete(const Iterator &firstToDelete, const Iterator &nextOfLastToDelete);
       
VOID SetValue(const Iterator &which, const T &value);
       
VOID SetValue(const Iterator &firstToDelete, const Iterator &nextOfLastToDelete, const T &value);

   
private:
       
T *m_pData;
    };

}
// namespace xl

#endif // #ifndef __XLARRAY_H_3B18D7E2_B52A_4D57_BE4B_657F9D17320D_INCLUDED__

 

xlList.h
#ifndef __XLLIST_H_2BEF1B3C_A056_4EC7_B5E3_9898E7945B54_INCLUDED__
#define __XLLIST_H_2BEF1B3C_A056_4EC7_B5E3_9898E7945B54_INCLUDED__


#include "xlDef.h"

namespace xl
{
   
template <typename T>
   
class List
   
{
   
public:
       
List();
       
List(const List<T> &that);
        ~
List();

   
private:
       
struct Node
       
{
           
T value;
           
Node *prev;
           
Node *next;
        };

   
public:
       
class Iterator
       
{
       
public:
           
Iterator();
           
Iterator(const List<T> *list);
           
Iterator(Iterator &that);

       
private:
           
List<T> *list;
           
Node *current;
           
BOOLEAN bof;
           
BOOLEAN eof;

       
public:
           
T &operator * ();
           
T *operator -> ();

       
public:
           
Iterator &operator = (Iterator &that);
           
BOOLEAN operator == (Iterator &that);
           
BOOLEAN operator != (Iterator &that);

       
public:
           
Iterator operator ++ ();
           
Iterator operator ++ (int);
           
Iterator operator -- ();
           
Iterator operator -- (int);
        };

   
public:
       
Iterator Bof();
       
Iterator Begin();
       
Iterator End();
       
Iterator Eof();

   
public:
       
List<T> &operator=(const List<T> &that);
       
BOOLEAN operator==(const List<T> &that) const;
       
BOOLEAN operator!=(const List<T> &that) const;

   
public:
       
BOOLEAN Empty();
       
UINT Count();

   
public:
       
VOID PushFront(const T &tValue);
       
VOID PushBack(const T &tValue);
       
VOID PopFront();
       
VOID PopBack();
       
VOID Insert(const Iterator &beforeWhich, const T &value);
       
VOID Insert(const Iterator &beforeWhich,
const Iterator &firstToInsert, const Iterator &NextOfLastToInsert);
       
Iterator Delete(const Iterator &which);
       
Iterator Delete(const Iterator &firstToDelete,
const Iterator &nextOfLastToDelete);

   
public:
       
Node *head;
       
Node *tail;
    };

}
// namespace xl

#endif // #ifndef __XLLIST_H_2BEF1B3C_A056_4EC7_B5E3_9898E7945B54_INCLUDED__

 

xlTree.h
#ifndef __XLTREE_H_6BB48AA6_133A_4E9F_944E_504B887B6980_INCLUDED__
#define __XLTREE_H_6BB48AA6_133A_4E9F_944E_504B887B6980_INCLUDED__


#include "xlDef.h"

namespace xl
{
   
template <typename T>
   
class Tree
   
{
   
public:
       
Tree();
       
Tree(const Tree<T> &that);
        ~
Tree();

   
private:
       
struct Node
       
{
           
T value;
           
Node *parent;
           
Node *left;
           
Node *right;
        };

   
private:
       
class Iterator
       
{
       
public:
           
Iterator();
           
Iterator(const Tree<T> *tree);
           
Iterator(Iterator &that);

       
private:
           
Tree<T> *tree;
           
Node *current;
           
BOOLEAN bof;
           
BOOLEAN eof;

       
public:
           
T &operator * ();
           
T *operator -> ();

       
public:
           
Iterator &operator = (Iterator &that);
           
BOOLEAN operator == (Iterator &that);
           
BOOLEAN operator != (Iterator &that);

       
public:
           
Iterator Parent();
           
Iterator Left();
           
Iterator Right();
        };

       
class PreorderIterator : public Iterator
       
{
       
public:
           
Iterator operator ++ ();
           
Iterator operator ++ (int);
           
Iterator operator -- ();
           
Iterator operator -- (int);
        };

       
class InorderIterator : public Iterator
       
{
       
public:
           
Iterator operator ++ ();
           
Iterator operator ++ (int);
           
Iterator operator -- ();
           
Iterator operator -- (int);
        };

       
class PostorderIterator : public Iterator
       
{
       
public:
           
Iterator operator ++ ();
           
Iterator operator ++ (int);
           
Iterator operator -- ();
           
Iterator operator -- (int);
        };

   
public:
       
Iterator Bof();
       
Iterator Begin();
        Iterator Eof();

   
public:
       
Tree<T> &operator=(const Tree<T> &that);
       
BOOLEAN operator==(const Tree<T> &that) const;
       
BOOLEAN operator!=(const Tree<T> &that) const;

   
public:
       
BOOLEAN Empty();
       
UINT Count();

   
public:
        VOID InsertLeft(const Iterator &beforeWhich, const T &value);
       
VOID InsertRight(const Iterator &beforeWhich, const T &value );
       
Iterator Delete(const Iterator &which);

   
public:
       
Node *head;
    };

}
// namespace xl

#endif // #ifndef __XLTREE_H_6BB48AA6_133A_4E9F_944E_504B887B6980_INCLUDED__

(Tree 的接口還沒完全考慮好,也不知道有沒有必要把 Node 獨立出來。)

這樣是否大概足夠了?敬請大家指教~

(再次重申一下,請不要來留個言說“干嗎要重新發明輪子?”、“XXX 不是很好用嗎?”之類的,謝謝!歡迎志同道合的朋友探討,如能為我解惑,那么非常感謝。)

posted on 2009-09-26 17:43 溪流 閱讀(679) 評論(18)  編輯 收藏 引用 所屬分類: C++

評論:
# re: 開始把庫搞起來了 2009-09-27 12:46 | 陳梓瀚(vczh)
碰巧我也再造輪子。我吸取了stl和.net的經驗做了一套collection出來,linq也實現了,string也實現了。現在正在做stream,還有無縫支持自定義的用戶類型。這就有4套子系統了,其中自反連接和兩兩互轉一共需要15個運算器(包括regex啦,linq啦,自定義語法分析器什么的)。

因為我是做編譯器的所以對復雜數據結構的靈活運算要求非常高,但是效率并沒有太苛求。完了我們可以交流一下。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 12:55 | 陳梓瀚(vczh)
然后我跟你說說VL++2.0的一些故事……現在已經推翻掉寫3.0了,其中的一些決定就是
1:不再typedef基礎類型
2:不再加前綴
3:大規模利用模板
4:加強各個模塊之間的關系,互操作性要變得很強

你可以考慮不走我的老路……  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 12:58 | 陳梓瀚(vczh)
于是最后提示一點,根據我前面幾年造輪子的實踐,獨立二叉樹的接口一點意義都沒有……  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 15:49 | 溪流
@陳梓瀚(vczh)

陳老師你好,我一年多前實習的時候因為公司不允許使用STL、MFC等等所有流行的庫,叫我們“用到的數據結構自己寫”。當時只寫了個 Vector、String,足以應付任務了。不過我就是從那時開始明白寫庫的意義,以及感受到用自己的庫的那種爽快的感覺的。

很佩服你的技術,粗看過你的代碼,我知道你把基礎數據結構全部實現了一遍,甚至regex,以及在代碼里寫 EBNF,等等。(我第一篇日志的開頭語不知道您看過了沒,呵呵)

我也想不走老路,不過有些東西可能不走一遍不會明白,所以我想可能先自然一點,到第二遍、第三遍再來總結以及回避已知問題。關于你說的4點,我比較想了解原因以及大概做法,可否稍微解釋下?特別是1和2,這個是現在就擺在我面前的。然后是3、4,我可以聽一聽,雖然可能不是馬上體會得到。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 15:51 | 溪流
@陳梓瀚(vczh)

你的意思是說 Tree::Node 沒必要暴露出來嗎?再問一下問一下,你覺得基礎庫里有必要存在二叉樹這種結構嗎?還有沒有必要以及可能包含圖的結構呢?  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 18:00 | OwnWaterloo
@溪流
1. 如非必要,不typedef基礎類型

為什么要typedef?
typedef是為了提供語意。

DWORD, WORD, BYTE的語意是固定長度整數。
stdint.h, cstdint, sys/stdin.h, windows.h 中已經有這樣的功能, 就盡可能去復用。
自己省事 —— 你有精力去為不同平臺定義出對應的DWORD, WORD, BYTE嗎?
既然上面的幾個文件中已經給出了這種功能, 并且在各個平臺下都測試過, 為什么不直接使用呢?

別人也省事。
需要明白一點:用戶與其依賴的庫通常不是線性結構,而是樹形結構。
A庫為了可移植性的去typedef DWORD, WORD, BYTE,
B庫也為了可移植性去typedef DWORD, WORD, BYTE,
一個客戶C, 同時需要A、B, 他該用哪個庫的DWORD?
這種作法是徒增不必要的概念。


對自己庫獨有, 并有可能改變的概念, 才可以考慮使用typedef 來建立一個語意。
比如time.h中的time_t, clock_t, 代表了兩個獨立的概念。
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 18:10 | OwnWaterloo
@溪流
2:不再加前綴

其實vczh同學放出來的代碼中的VL_前綴……
我覺得看上去是很傷眼的……
當然, 這是口味問題。


關于這個問題:
"但是,問題是,當 using namespace xl 并 #include <Windows.h> 以后,隨手寫一個“DWORD”,就會有歧義了。如果用的時候要寫成 xl::DWORD,那還不如現在就命名成 XL_DWORD 好了"

首先, 不必定義xl::DWORD。
對于其他情況, 名字空間相對于前綴是有一些優勢的。
1. 如果存在歧義, 無論是名字空間,還是前綴, 都必須使用全稱。
2. 不存在歧義的時候, 名字空間可以打開, 可以別名。 而前綴必須時刻都帶著, 永遠逃不掉。
3. 如果不小心, 兩個使用前綴的庫都出現了相同名字, 前綴技術就很麻煩。
A庫是個做網絡的, 有一個 net_f,
B庫也是個做網絡的, 依然一個 net_f,
要同時使用兩個庫, 就需要自己去寫轉發函數。

而名字空間, 可以一開始就很長。
namespace net_byA { void f() }
namespace net_byB { void f() }


只使用A(或B)的用戶,就可以使用別名:
namepsace net = net_byA(B);
net::f;

如果同時使用A、B的用戶, 只好:
net_byA::f;
net_byB::f;

也比自己寫轉發函數要強。

總之, 名字空間是一種更靈活的方式。

如果決定使用C++編寫庫, 而且不考慮過分古董的編譯器, 就應該選用名字空間。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 18:26 | OwnWaterloo
@溪流

各種現有的流行的庫中, 實現了侵入式容器的比較少。
大都是非侵入式容器。

侵入式容器我只在如下一些庫中見到過:
linux/list.h, linux/rbtree.h
sourceforge有個叫libaasdl的項目,有一個GDST(generic data-structure template)子庫中的一些是侵入式的(還有一些我沒看完)

SGI-STL中4種關聯容器底層使用的是同一種容器,_Rb_tree。
它是非侵入式的。
但是構建它的_Rb_tree_base、_Rb_tree_base_iterator都是非侵入式的。
SGI-STL沒有構建出一個侵入式的RbTree層, 而是直接使用侵入式的_Rb_tree_base,和_Rb_tree_base_iterator構建出了非侵入式的_Rb_tree。
稍微有點可惜。
不過即使有一個侵入式的RbTree, SGI-STL也是不會將其公開出來的。


如果想練手, 可以考慮構建一套侵入式的容器, 比僅僅重復STL中的東西來得有意義。

還有, STL中沒有樹式的堆。
heap相關的那幾個函數都是對random_access的線性表使用的。
也可以考慮在這里做做文章。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 18:51 | OwnWaterloo
const VOID *NULL = 0;
在C++中, 這樣定義NULL是行不通的。
 
普遍的做法是直接使用0,或者stddef.h, cstddef 中的NULL宏:
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0) /* 這是C中的做法 */
#endif
 
void* 在C中可以隱式轉換到其他類型指針。
但C++不行。
 
 
或者, 更激進一點, 使用nullptr:
nullptr
因為C++0x將引入nullptr作為關鍵字。
使用nullptr,算是"向前兼容"吧…… 等轉到C++0x時,就可以直接使用真正的nullptr了。
 
上面最后一種nullptr和C++0x中的語意最相似, 不過不一定能在所有編譯器中都通過。
至少要支持成員函數模板才行。
如果不支持匿名類可以改用別的方式實現。
 
 
 
 typedef struct interface;
這是什么語法?
這也是徒增概念的地方。
 
C++程序員如果不知道下面的代碼是一個interface
struct Ixxx {
    virtual ~Ixxx();
    virtual ...
};
 
將struct 換成interface對他的幫助也不大。
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 19:10 | OwnWaterloo
不叫"跨容器"的iterator。
而是iterator符合特定的concepts。
不過你說對了, 它確實和模板有關。
 
比如,使用一對forwarding_iterator構造vector的偽代碼:
concepts
 
vector有一個構造函數模板。
只要FotIt 滿足forwarding_iterator的概念,上面的構造函數就可以生成。
forwarding_iterator 要支持(但不限于)++, *, 因為上面的代碼使用了這2個操作符。
vector的實現也不會是上面那樣, 不會調用new 去默認構造一次。
會使用其allocator來分配,并使用uninitialized_copy。
不過那樣就看不到vector() 對forwarding_iterator的要求了。
 
 
這是C++中的方式,GP的,基于concepts的方式。C#中可是沒得這么爽的哦。
并且, GP的、基于concepts的方式, 也可以退化成OOP的,基于interface的方式。
反之不行, 因為concepts的偶和性更低。
 
 
不僅僅是容器。 整個STL中的組件都是通過concepts來協作而非interface。
如果你喜歡struct Iterator的方式, 或者IComparable , 也可以這么搞一套。
代碼不會比GP來得少, 效率不會比GP來得高, 也不會比GP靈活 —— GP可以退化為基于interface, 反之不行。
 
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 19:10 | OwnWaterloo
上面貼的代碼有問題, 重新貼一下……
 
template<typename T,  >
class vector {
    T
* first_;
    T
* last_;
public:
    template
<class ForIt>
    vector(ForIt first,ForIt last) {
        difference_type d 
= distance(first,last);
        first_ 
= new T[ d + padding ];
        last_ 
= first_ + d;
        
for (T* p = first;first!=last;++first,++p)
            
*= *first;
    }
};
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 20:33 | 溪流
@OwnWaterloo

先謝過您的這么詳細的指點。等我仔細看過后再來提后續問題:)  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 22:35 | 溪流
@OwnWaterloo

1、關于 typedef

第一,我想我要寫的庫要保持獨立性。如果去包含了 Winows.h 了,那么就失去了這一部分的獨立性了。在做容器方面的東西的時候,實際上我根本不會用到 Windwos API,而這一 include,增加無畏的依賴的同時,還把平臺陷死了(雖然我不準備搞多么跨平臺的東西,但是明明可以不依賴的,還是不要去依賴,是嗎?)

我想,庫的用戶可能不需要去寫太多次 a::DWORD、b::DWORD,只要他們的定義是兼容的,傳入的值就可以用。

其實我最頭痛的就是 Windows.h 把這些名字都占去了,而且是全局的,是的用戶無法簡單地寫一個 DWORD 來定義 Windows.h 中的 DWORD 了。我知道加前綴不是好的解決方案,可是還有其他一套如此通用的名字嗎?
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 22:45 | OwnWaterloo
@溪流
用stdint.h。 把這個棘手的工作交給編譯器提供商。
并且, 你實現容器庫的時候, 需要DWORD么……


> 只要他們的定義是兼容的,傳入的值就可以用。
你要去檢查。 是否每個庫都是兼容的。

另一種方式是只依賴于一處定義。比如stdint.h


msvc沒有提供stdint.h, 因為它不支持C99。
網上有一個stdint.h for msvc, 使用BSD3條款的許可證。

或者自己寫:

msvc 提供了 __intN擴展。
所以 intN_t uintN_t 很好處理
int_leastN_t, 這個本來就不能假設它的寬度, 按字面來即可。

uintptr_t, intptr_t 可以包含basetsd.h
typedef INT_PTR intptr_t;
typedef UINT_PTR uintptr_t;


現在你代碼中依賴的就是:
(u)intN_t, (u)int_fastN_t ,, (u)intptr_t, (u)intmax_t 等等。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-27 23:58 | 溪流
@OwnWaterloo

是的,現在是用不著 DWORD,但是以后一些功能庫會用到。
stdint.h 中的類型名稱似乎也不怎么干凈利索。
要不就直接用標準名稱好了?只是我很不喜歡 unsigned int, size_t 這種寫法。  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-28 00:17 | OwnWaterloo
@溪流
這個…… 其實是個口味問題 …… all fine.
我比較懶…… 有現成的就喜歡用現成的…… so ……

  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-28 00:27 | 溪流
@OwnWaterloo

打算這樣,如何?

namespace xl
{
    typedef unsigned 
char uchar;
    typedef unsigned 
short ushort;
    typedef unsigned 
int uint;
    typedef unsigned 
long ulong;
    typedef 
long long longlong;
    typedef unsigned 
long long ulonglong;

    typedef wchar_t wchar;
    typedef unsigned wchar uwchar;

    typedef __int8 int8;
    typedef __int16 int16;
    typedef __int32 int32;
    typedef __int64 int64;

    typedef unsigned int8 uint8;
    typedef unsigned int16 uint16;
    typedef unsigned int32 uint32;
    typedef unsigned int64 uint64;

    
struct
    
{
        template
<typename T>
        
operator T*() const
        
{
            
return 0;
        }


    }
 nullptr;

}
 // namespace xl


我的目的主要是為了書寫簡潔,其他的其實對我來說關系不大,暫時主要考慮 Win + MSVC 平臺。nullptr 的定義真的好精妙!
  回復  更多評論
  
# re: 開始把庫搞起來了 2009-09-28 00:40 | OwnWaterloo
@溪流
nullptr是《eff cpp》中提到的。

對于int和指針的重載:
void f(int );
void f(void* );

f(0); // f(int );
f(NULL); // 如果是stddef.h 中的NULL, f(int );
f(nullptr); // 書中提到的那個nullptr, 會選中 f(void* );

如果還有另一種指針:

void f(int* ); nullptr 會引起歧義。

當然, 最好是避免這種重載……

  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品视频播放| 欧美伊人影院| 亚洲欧美日韩国产一区| 亚洲精选久久| 国产精品v日韩精品| 亚洲网站在线观看| 亚洲手机成人高清视频| 欧美午夜精品| 另类av一区二区| 欧美精品激情在线| 亚洲欧美日韩国产一区二区| 亚洲男女自偷自拍| 亚洲欧洲在线观看| 亚洲一区二区三区四区在线观看| 欧美日韩精品久久久| 久久国产综合精品| 欧美色网一区二区| 欧美国产第一页| 欧美视频专区一二在线观看| 久久久天天操| 国产精品午夜av在线| 亚洲区在线播放| 国产亚洲激情| 中文国产成人精品| 日韩午夜视频在线观看| 久久久.com| 久久久久久一区二区| 国产精品a久久久久久| 91久久线看在观草草青青| 在线成人国产| 久久手机精品视频| 欧美福利电影在线观看| 黄色亚洲免费| 一区二区三区波多野结衣在线观看| 先锋影音久久| 久久噜噜噜精品国产亚洲综合| 国产精品久久久久久超碰 | 国产欧美亚洲一区| 一本色道88久久加勒比精品| 一区二区av在线| 欧美日韩一区国产| 亚洲午夜免费福利视频| 久久精品一区二区三区四区| 国产一区二区三区电影在线观看| 午夜日韩在线观看| 久久亚洲精品一区二区| 亚洲激情网站| 欧美日韩日韩| 欧美在线观看www| 亚洲电影视频在线| 亚洲欧美日韩系列| 最近中文字幕mv在线一区二区三区四区| 久久久综合免费视频| 日韩视频中文| 久久免费国产| 亚洲欧美日韩另类| 99精品久久| 激情综合网激情| 国产精品日韩电影| 免费成人高清视频| 欧美一区二区三区电影在线观看| 亚洲欧洲一区二区天堂久久| 亚洲专区一区| 亚洲美女黄色片| 亚洲黄色在线观看| 国产一区二区三区高清播放| 欧美日韩美女在线| 女女同性女同一区二区三区91| 亚洲欧美日韩国产精品| 国产精品99久久久久久久久| 欧美激情亚洲国产| 国内精品视频在线播放| 欧美私人网站| 欧美午夜国产| 国产精品久久久久一区二区三区共| 免费欧美网站| 欧美日韩免费观看一区| 欧美日韩精品一区二区在线播放| 男女精品网站| 欧美全黄视频| 国产精品美女久久| 国产人成精品一区二区三| 国产一区二区久久精品| 国产综合视频在线观看| 亚洲国产美女久久久久| 亚洲精品中文字幕在线| 亚洲特级毛片| 久久久亚洲高清| 亚洲人成啪啪网站| 午夜精品久久久久久| 快射av在线播放一区| 国产精品久久久久久久久久免费看 | 欧美亚洲色图校园春色| 性做久久久久久| 久久精品亚洲一区二区| 欧美精品自拍| 国产三区二区一区久久| 亚洲国产精品久久久久婷婷老年| 亚洲视频一二区| 欧美大片一区二区三区| 一区二区日韩伦理片| 欧美亚洲视频在线看网址| 欧美黄污视频| 国产亚洲欧美激情| 在线中文字幕不卡| 欧美成人在线影院| 欧美一级久久| 日韩亚洲国产欧美| 欧美在线一二三区| 国产精品久久久久久久久免费桃花 | 欧美激情片在线观看| 亚洲午夜性刺激影院| 欧美日本簧片| 99爱精品视频| 亚洲日韩欧美一区二区在线| 久久综合给合久久狠狠狠97色69| 国产精品一国产精品k频道56| 亚洲精品综合久久中文字幕| 久久亚洲欧美| 久久久综合激的五月天| 亚洲国产精品一区制服丝袜| 久久先锋资源| 欧美www在线| 91久久在线| 亚洲大片在线观看| 欧美日韩一区精品| 欧美一区91| 性欧美8khd高清极品| 国产日韩欧美成人| 欧美在线观看视频一区二区三区| 激情丁香综合| 久久综合给合久久狠狠狠97色69| 亚洲欧美精品伊人久久| 国产精品亚洲综合色区韩国| 久久精品日韩一区二区三区| 欧美激情片在线观看| 亚洲一区二区三区四区视频| 欧美一区成人| 你懂的亚洲视频| 欧美亚洲一区二区在线| 亚洲一区二区高清| 最新69国产成人精品视频免费| 日韩视频不卡| 亚洲电影免费在线| 亚洲调教视频在线观看| 亚洲高清不卡在线| 国产精品日韩欧美一区| 久久精品最新地址| 亚洲黄色大片| 国产一区二区三区久久悠悠色av| 蘑菇福利视频一区播放| 国产精品电影网站| 欧美成人精品1314www| 国产一区在线播放| 亚洲欧美成人| 一区二区三区视频免费在线观看| 久久久精品国产99久久精品芒果| 亚洲影音一区| 女人天堂亚洲aⅴ在线观看| 亚洲欧美国产日韩天堂区| 亚洲综合视频在线| 亚洲视频一区二区| 美女精品自拍一二三四| 欧美77777| 久久精品国产欧美亚洲人人爽| 激情欧美一区二区三区在线观看| 欧美国产日本韩| 久久性天堂网| 亚洲国产婷婷香蕉久久久久久| 亚洲美女毛片| 国产欧美日韩不卡| 免费欧美日韩| 欧美亚洲视频一区二区| 欧美激情第10页| 亚洲欧美日韩区| 91久久久久久国产精品| 欧美香蕉大胸在线视频观看| 午夜日韩av| 亚洲欧洲一级| 久久综合色8888| 欧美一级大片在线观看| 黄色日韩精品| 国产精品视频九色porn| 蜜桃伊人久久| 欧美在线精品免播放器视频| 亚洲国产日韩欧美在线99 | 午夜视频久久久| avtt综合网| 在线观看一区二区视频| 国产精品成人观看视频免费 | 这里是久久伊人| 最近看过的日韩成人| 欧美粗暴jizz性欧美20| 久久九九热re6这里有精品| 亚洲在线观看视频| 久久久国产成人精品| 久久精品国产亚洲一区二区| 亚洲欧美日韩一区在线| 中文精品视频| 亚洲中午字幕|