今天看到accelerated c++上有個簡單的vector容器的實現Vec,就再vs2008上編譯了下:
///// Vec.h
#ifndef GUARD_VEC_H
#define GUARD_VEC_H
#include <iostream>
#include <iterator>
#include <memory>
//#include <xmemory>
template <class T>
class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
Vec() {create();} //默認的構造函數
explicit Vec(size_type n,const T& t=t()) {create(n,t);} //單參數或者兩個參數構造函數
Vec(const Vec& v) {create(v.begin(),v.end());} //拷貝構造函數
Vec& operator=(const Vec&); //賦值構造函數
~Vec() {uncreate();} //析構函數
size_type size() { return avail-data; } //定義類的大小,ptrdiff_t自動轉化成size_t
void push_back(const T& t)
{
if (avail==limit)
{
grow();
}
unchecked_append(t);
}
//重載【】
T& operator[] (size_type i) { return data[i]; }
const T& operator[] (size_type i) const { return data[i]; }
//定義begin和end,都有兩個版本
iterator begin() {return data;}
const_iterator begin() const {return data;}
iterator end() {return avail;}
const_iterator end() const {return avail;}
protected:
private:
iterator data; //Vec中得初始值
iterator avail; //Vec中得結束值
iterator limit; //Vec中空間分配的結束值
std::allocator<T> alloc; //注意此處std
//創造函數,負責內存管理
void create();
void create(size_type,const T&);
void create(const_iterator,const_iterator);
//銷毀元素,返回內存
void uncreate();
//支持push_back函數
void grow();
void unchecked_append(const T&);
};
#endif
//// Vec.cpp
#include <iostream>
#include "Vec.h"
//#pragma comment(lib,"ws2_32.lib")
using namespace std;
//拷貝構造函數
template <class T>
Vec<T>& Vec<T>::operator=(const Vec& v)
{
if (&v!=this) //檢查是否為自我賦值,很重要,必須有
{
uncreate(); //清空左值的元素
create(v.begin(),v.end()); //拷貝元素到左值
}
return *this;
}
//push_back函數中內存增長策略函數
template <class T>
void Vec<T>::grow()
{
size_type new_size=max(2*(limit-data),ptrdiff_t(1)); //防止剛開始內存空間為0的情況
iterator new_data=alloc.allocate(new_size); //返回首地址
//把前兩個參數指定的元素復制給第三個參數表示的目標序列,返回末尾元素的下一個迭代器
iterator new_avail=uninitialized_copy(data,avail,new_data);
uncreate(); //釋放原先的空間
data=new_data;
avail=new_avail;
limit=data+new_size;
}
//向申請的內存中添加元素
template <class T>
void Vec<T>::unchecked_append(const T& val)
{
//在未初始化的空間構建一個對象,參數1插入對象的位置指針,參數2需要添加的對象
alloc.construct(avail++,val);
}
//申請內存的函數create
template <class T>
void Vec<T>::create()
{
data=avail=limit=0;
}
template <class T>
void Vec<T>::create(size_type n,const T& val)
{
data=alloc.allocate(n); //申請內存空間,但是不初始化
limit=avail=data+n;
uninitialized_fill(data,limit,val); //進行初始化
}
template <class T>
void Vec<T>::create(const_iterator i,const_iterator j)
{
data=alloc.allocate(j-i);
limit=avail=uninitialized_copy(i,j,data);
}
//回收內存
template <class T>
void Vec<T>::uncreate()
{
if (data) //如果data是0,我們不需要做什麼工作
{
iterator it=avail;
while (it!=data)
alloc.destroy(--it); //銷毀沒個元素,為了與delete行為一致,采用從後向前遍歷
alloc.deallocate(data,limit-data); //內存釋放,函數需要一個非零指針
//因此,檢測data是否為零
}
data=limit=avail=0;
}
//// 測試的main函數
#include <iostream>
#include "Vec.h"
using namespace std;
int main()
{
Vec<int> a;
Vec<int> b;
a.push_back(12);
b=a;
return 0;
}
結果編譯後出現下面錯誤:
1>------ 已啟動生成: 項目: Accelerated, 配置: Debug Win32 ------
1>正在編譯...
1>Vec.cpp
1>Vec_example.cpp
1>正在生成代碼...
1>正在鏈接...
1>Vec_example.obj : error LNK2001: 無法解析的外部符號 "public: class Vec<int> & __thiscall Vec<int>::operator=(class Vec<int> const &)" (??4?$Vec@H@@QAEAAV0@ABV0@@Z)
1>Vec_example.obj : error LNK2001: 無法解析的外部符號 "private: void __thiscall Vec<int>::create(void)" (?create@?$Vec@H@@AAEXXZ)
1>Vec_example.obj : error LNK2001: 無法解析的外部符號 "private: void __thiscall Vec<int>::uncreate(void)" (?uncreate@?$Vec@H@@AAEXXZ)
1>Vec_example.obj : error LNK2001: 無法解析的外部符號 "private: void __thiscall Vec<int>::unchecked_append(int const &)" (?unchecked_append@?$Vec@H@@AAEXABH@Z)
1>Vec_example.obj : error LNK2001: 無法解析的外部符號 "private: void __thiscall Vec<int>::grow(void)" (?grow@?$Vec@H@@AAEXXZ)
1>E:\360data\重要數據\我的文檔\Visual Studio 2008\Projects\Accelerated\Debug\Accelerated.exe : fatal error LNK1120: 5 個無法解析的外部命令
1>生成日志保存在“file://e:\360data\重要數據\我的文檔\Visual Studio 2008\Projects\Accelerated\Accelerated\Debug\BuildLog.htm”
1>Accelerated - 6 個錯誤,0 個警告
========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========
上面問題不知道怎麼解決,就開始google解決方案: 模板不支持分離編譯, 把你模板類的聲明和實現放到.h文件裡面 。按照這個說的把.h和.cpp文件合並後,果然可以了。