2017-10-12 46 views
2

我想編寫一個模板函數,可以使用std::vector將數據傳遞給C風格的API(在我的使用案例中,特別是OpenGL)。該代碼我想出了這個樣子的:未定義的行爲,以陣列/矢量結束地址?

template<typename T> 
void pass_data(GLuint buffer, std::vector<T> const& data) { 
    glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW); 
} 

這似乎是一個簡單的解決方案,直到它發生,我認爲T可能會導致&t[1] - &t[0] != sizeof(T)是正確對齊限制,這將意味着這個函數會不準確地通過整個陣列。所以我重寫功能做到這一點,而不是:

template<typename T> 
void pass_data(GLuint buffer, std::vector<T> const& data) { 
    glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    glBufferData(GL_ARRAY_BUFFER, static_cast<size_t>(&data[data.size()] - &data[0]), data.data(), GL_STATIC_DRAW); 
} 

但是,目前還不清楚,我認爲這樣的一個得票最多的高端訪問是安全的(我敢肯定,這是不確定的行爲)。確保我的函數準確評估向量的字節大小並將正確的參數傳遞給基礎C-API調用的最佳方法是什麼?

注意:我不想討論關於如何使用OpenGL [誤]的問題。我只關注精確模擬矢量的指針+大小的願望。

+0

我懷疑你會被允許創建一個這樣的矢量。它保證連續的存儲。那麼你能給出一個實際用例的例子嗎?我並不是說這是不可能的,但是你不得不原諒我認爲這有點令人擔憂。 – StoryTeller

+2

'&t [1] - &t [0]!= sizeof(T)'在什麼情況下這是真實的?你的'T'跨越過程邊界? – PnotNP

+1

減去兩個指針不會給你以字節爲單位的大小,它給出你已經知道是'data.size()'的元素的大小。你的第二個例子*不等於第一個例子。 –

回答

4

是的,data[data.size()]是未定義的行爲。

幸運的是,你不需要任何這樣的事情,因爲(char*)&data[1] - (char*)&data[0] == sizeof(T)實際上是保證任何類型T。所以回到data.size() * sizeof(T)

但我也想補充一個

static_assert(std::is_trivially_copyable<T>::value, "Invalid type"); 

是有點更安全。