2014-06-10 25 views
37

考慮下面的代碼段,這是通過C++編譯器11完全可以接受的:在C++ 11中是否存在零大小的std :: array的原因?

#include <array> 
#include <iostream> 

auto main() -> int { 
    std::array<double, 0> A; 

    for(auto i : A) std::cout << i << std::endl; 

    return 0; 
} 

根據標準§23.3.2.8 [零大小的數組]:

1陣列應提供對特殊情況N == 0的支持。

2N == 0,begin() == end() ==唯一值的情況下。未指定返回值
data()

3對於零大小的數組,調用front()back()的效果未定義。

4成員函數swap()應該有一個noexcept-speci fi cation相當於 noexcept(true)

如上顯示,零尺寸std::array s爲在C++ 11完全允許的,相反具有零門尺寸的陣列(例如,int A[0];)在那裏它們被明確禁止的,但它們是由一些編譯器允許(例如, GCC)以未定義的行爲爲代價。

考慮到這個「矛盾」,我有以下問題:

  • 爲什麼C++委員會決定允許零大小std::array S'

  • 有沒有什麼有價值的用途?我能想到的

+18

可能與容器一致,並使一些通用的東西更容易。 – chris

+1

一個可能的考慮是,即使任何實現對零大小的數組都有困難,他們也應該對'std :: array '進行部分特化。 – hvd

+2

模板元程序通常是遞歸的,遞歸最低限度爲0而不是1 ...但我承認我在這種情況下構建一個實際的示例時遇到了問題 – Nemo

回答

40

如果你有一個通用函數,那麼如果該函數針對特殊參數隨機中斷,那麼這是不好的。例如,讓我們說你可以有一個模板函數,它N隨機元素形成向量:

template<typename T, size_t N> 
std::array<T, N> choose(const std::vector<T> &v) { 
    ... 
} 

沒有的,所以如果如果N由於某種原因,原來是零這會導致不確定的行爲或編譯器錯誤。

對於原始數組,這個限制的一個原因是你不想要類型爲sizeof T == 0,這會導致與指針算術結合的奇怪效果。如果您沒有爲其添加任何特殊規則,則具有零元素的數組的大小爲零。

std::array<>是一類和類總是有大小> 0。所以你不std::array<>碰到這些問題,並且沒有模板參數的任意限制了一致的接口是優選的。

4

的一個用途是零個長度數組的返回是可能的,具有以下功能:進行具體檢查。

例如,請參閱std::array函數empty()的文檔。它具有以下的返回值:

true if the array size is 0, false otherwise. 

http://www.cplusplus.com/reference/array/array/empty/

我想返回,並檢查其長度爲0的數組與用於STL類型的其它實施方式中的標準線,爲例如的能力。矢量和地圖,因此很有用。

+11

請不要引用cplusplus.com。大多數條目不完整或錯誤。改用http://en.cppreference.com/w/cpp/container/array。 – kay

+4

@Kay但它不是在這種情況下?何時它不完整或錯誤? –

+0

@我可以看到它偶爾不完整的更晦澀的東西 - 但錯了?什麼時候? – druckermanly

1

與其他容器類一樣,能夠擁有一個表示一組事物的對象並使該數組成爲空或變爲空是有用的。如果這是不可能的,那麼需要創建另一個對象或管理類來以合法的方式表示該狀態。擁有所有容器類中已有的能力是非常有用的。在使用它的時候,只需要養成將數組作爲一個容器的習慣,這個容器可能是空的,並且在指向它的成員之前檢查它的大小或索引,以防它指向任何東西。

1

實際上有不少情況下,你想能夠做到這一點。它也出現在很多其他語言中。例如,Java實際上有Collections.emptyList(),它返回的不僅是大小爲零的列表,而且不能被擴展,調整大小或修改。

一個示例用法可能是如果您有一個班級代表該班級中的公交車和乘客列表。該列表可能會延遲初始化,僅在乘客登機時創建。如果有人呼叫getPassengers(),那麼可以返回一個空列表,而不是每次僅創建一個新列表以報告空。

返回null也會對班級的內部效率起作用 - 但是會讓生活變得更加複雜,因爲每當您撥打getPassengers()時,您都需要對結果進行空檢查。相反,如果你得到一個空列表,那麼只要你的代碼沒有假設列表不是空的,你不需要任何特殊的代碼來處理它爲空。

相關問題