2016-01-15 134 views
0

下面的代碼不compile.:-奇怪行爲模板

#include <vector> 

template <typename T> 
struct B; 

template <typename T> 
struct A 
{ 
    B<T> _a; 
}; 

template <typename T> 
struct B 
{ 
    A<T> _b; 
}; 


int main() 
{ 
    B<int> c; 

    return 0; 
} 

從第一看的原因接縫爲A和B之間的循環依賴然而,當代替使用B型_b部件明確地,使用向量(存儲實際對象,而不是指向它的指針)。像這樣

#include <vector> 

template <typename T> 
struct B; 

template <typename T> 
struct A 
{ 
    std::vector<B<T>> _a; 
}; 

template <typename T> 
struct B 
{ 
    A<T> _b; 
}; 


int main() 
{ 
    A<int> c; 

    return 0; 
} 

,一切工作正常。問題是爲什麼?如果向量只需要B的大小,T>結構,那麼在第一個例子中,A的任何部分都是因爲它不調用任何B的函數。

回答

2

在您的第一個示例中,sizeof(A<int>)sizeof(B<int>)是遞歸定義的。 問問自己:什麼是sizeof(A<int>)

您無法回答,因爲sizeof(A<int>)取決於sizeof(B<int>)並遞歸。

在第二個例子中sizeof(A<int>)sizeof(std::vector<B<int>>)這是不變的,的確std::vector做了堆分配。

嘗試用std::array代替std::vector,您將再次遇到同樣的問題。事實上,std::array的大小取決於元素的大小。

1

std::vector的實現顯然只有指針和/或引用B<T>作爲成員。由於引用和指向不完整類型的指針是合法的,程序編譯正確。

+0

我想你是對的。然而,如何調整向量的邏輯大小,複製應該被執行,並且爲了複製c'tor應該被使用,我猜你不能以不完整的類型調用它。還有什麼我真的可以欺騙編譯器,而不是聲明類型X的成員,我將定義包含未定義類型的大小爲1的向量。我很困惑它爲什麼有效。 – Boris

+0

該向量的成員函數在主程序定義中比程序稍後的時間點實例化。 C++有一些叫做「實例化點」的東西。看例如https://stackoverflow.com/questions/3810269/templates-name-resolutionpoint-of-instantiation-can-any-one-tell-some-more。這可以幫助你理解這種代碼是如何工作的。 –