2012-05-25 48 views
4

這是不確定的行爲?我可以施放一個std ::數組來切片嗎?還是有什麼我可以用來代替?

std::array<int, 5> x = {3, 5, 1, 2, 3}; 
std::array<int, 3>& y = *reinterpret_cast<std::array<int, 3>*>(&x[1]); 
for(int i = 0; i != 3; i++) { 
    std::cout << y[i] << "\n"; 
} 

也許是的,但我真的覺得應該有切片std::array安全方式。

編輯:繼拉狄克的建議:

template<unsigned N, unsigned start, unsigned end, typename T> 
std::array<T, end - start>& array_slice(std::array<T, N>& x) 
{ 
    static_assert(start <= end, "start <= end"); 
    static_assert(end <= N-1, "end <= N"); 
    return *reinterpret_cast<std::array<T, end - start>*>(&x[start]); 
} 

編輯:好吧,我決定,我很不滿意std::array S和將移動到別的東西,任何想法?

+0

*但我真的覺得應該有一個安全的方式來切分std :: arrays *寫一個模板函數'array_cast'。 – 2012-05-25 20:13:18

回答

-1

放置新東西怎麼樣?

#include <array> 
#include <iostream> 
#include <iterator> 

template<typename T, std::size_t N> 
struct array_slice : public std::array<T,N> { 
    ~array_slice() = delete; 
}; 

int main() { 
    std::array<double,4> x_mu{0.,3.14,-1.,1.}; 
    std:: cout << &x_mu << std::endl; 

    { 
     auto slicer = [] (std::array<double,4>& ref) { 
      array_slice<double,3>* p = new (&ref) array_slice<double,3>; 
      return p; 
     };  

     std::array<double,3>& x_ = *slicer(x_mu); 
     std::copy(x_.begin(),x_.end(), 
       std::ostream_iterator<float>(std::cout," ")); 
     std:: cout << std::endl; 
     std:: cout << &x_ << std::endl; 
    } 

    std::copy(x_mu.begin(),x_mu.end(), 
       std::ostream_iterator<float>(std::cout," ")); 
} 
+1

這是各種未定義的行爲。通過重用內存來結束舊數組元素的生命週期。您可以在相同位置創建新元素,但允許現有引用/指針在同一位置引用新對象的規則僅適用於完整對象,並且這些是聚合的子對象。根據元素類型的不同,它可能會有不重要的默認初始化來清除現有值,或者最終可能會得到未初始化的對象(不能假定它們取先前存在於其內存位置的值)。 –

6

是的,那是未定義的行爲。您正在接受一種類型的信息,並將其輸入另一個類型。的確,使用reinterpret_cast應該是一個大紅旗,因爲「這裏有龍!」對於切片數組,這不會發生。 A std::array包含值;其中一部分將包含引用到該數組的一部分。因此,它不會是std::array。您可以複製數組片,但不使用std::array。您需要使用std::vector,因爲它允許調用構造函數以及從一系列值構造。記住:std::array只是一個圍繞C風格數組的更好的包裝。

該委員會正在研究模板類,這正是它所說的:對T類型的某個數組段的引用。這可能是一個普通的C風格陣列,std::vectorstd::array,或只是一些內存分配new T[]。有some library implementations of the class already,但沒有任何標準化。


繼拉狄克的建議:

隱藏未定義行爲的功能並不能使它定義的行爲。你可以嘗試假裝它不是未定義的,但它仍然是。在你使用reinterpret_cast的那一刻,你會放棄生活在C++的土地上。

+0

我同意你所說的,但我認爲標準中的'std :: array'基本上沒有切片。 –

+2

@Giovanni:只有當你試圖將它用於不適合使用的東西時,它纔會被破壞。這就像是說'std :: list'因爲它的元素不是連續存儲而被破壞的,或者'std :: map'被破壞了,因爲它不提供O(1)查找。您期待錘子起到螺絲刀的作用。 –

+0

這沒有任何意義。我不是在說錘子。 C++的'std :: array's應該改進C數組,就像在提供更多的功能(對編譯時已知邊界進行類型檢查)一樣,然而對於C數組完全有效的東西不再適用於C++。絕對沒有理由。我認爲,在這方面,我非常有資格說STL API已經被破解了。 –

相關問題