2011-01-21 34 views
11

我喜歡與給定的規模和價值創造的載體,例如像這樣:我如何初始化一個std :: vector大小參數,並讓每個對象獨立構造?

std::vector<std::string> names(10); 

然而,這幾次這導致了意想不到的結果。例如在下面的代碼每個UniqueNumber原來具有相同的價值:

#include <iostream> 
#include <string> 
#include <vector> 


struct UniqueNumber 
{ 
    UniqueNumber() : mValue(sInstanceCount++) 
    { 
    } 

    inline unsigned int value() const 
    { 
     return mValue; 
    } 

private: 
    static unsigned int sInstanceCount; 
    unsigned int mValue; 
}; 


int UniqueNumber::sInstanceCount(0); 


int main() 
{ 
    std::vector<UniqueNumber> numbers(10); 
    for (size_t i = 0; i < numbers.size(); ++i) 
    { 
     std::cout << numbers[i].value() << " "; 
    } 
} 

控制檯輸出:

explicit vector(size_type __n, 
       const value_type& __value = value_type(), 
       const allocator_type& __a = allocator_type()); 

0 0 0 0 0 0 0 0 0 0 

看的std :: vector的構造函數時,它有一定道理

顯然,矢量是用相同對象的副本初始化的。

是否還有一種方法讓每個對象默認構造?

回答

4

generategenerate_n是專門爲您想要做的事情而設計的。這裏有一個完整的例子:

#include <algorithm> 
#include <vector> 
#include <iterator> 
#include <iostream> 
using namespace std; 

class Foo 
{ 
public: 
    Foo() : n_(++water_) {}; 
    operator unsigned() const { return n_; } 
private: 
    static unsigned water_; 
    unsigned n_; 
}; 

Foo make_foo() 
{ 
    return Foo(); 
} 

unsigned Foo::water_ = 0; 

int main() 
{ 
    vector<Foo> v_foo; 
    generate_n(back_inserter(v_foo), 10, &make_foo); 
    copy(v_foo.begin(), v_foo.end(), ostream_iterator<unsigned>(cout, " ")); 
} 

輸出:1 2 3 4 5 6 7 8 9 10

+0

感謝您提供非侵入式解決方案。 – StackedCrooked

+0

@StackedCrooked,實際上它是侵入性的,我寧願使用'make_foo'的對象,它會好得多。 –

3

您需要添加一個拷貝構造函數:

UniqueNumber(const UniqueNumber& un) : mValue(sInstanceCount++) 
{ } 

std::vector填充構造並沒有叫你的默認構造函數。相反,它調用隱含存在的默認副本構造函數。那個構造函數當然不會增加你的內部靜態計數器變量。

您還需要定義一個賦值運算符。

但是,使用具有內部靜態計數器的對象與std::vector會產生意想不到的結果,因爲該向量可以內部複製 - 構建/分配對象,因爲它看起來合適。所以這可能會干擾你在這裏需要的複製語義。

+0

+1你打我吧:) – Zevan

+0

嗯,這是調用默認的構造函數一次,然後要求它增加了每個元素的默認拷貝構造函數英寸。結果可能仍然有點意外,因爲如果您沒有注意到這些值,那麼值將從1開始,而不是0。 –

+0

這將修復我的示例,但現在副本不再與原始相同。我認爲這是非常不直觀的行爲。 – StackedCrooked

4

向量是複製構造初始化元素。

試一下:

#include <iostream> 
#include <string> 
#include <vector> 


struct UniqueNumber 
{ 
    UniqueNumber(bool automatic = true) 
     : mValue(automatic?sInstanceCount++:Special) 
    { } 

    UniqueNumber(UniqueNumber const& other) 
     : mValue(other.mValue==Special?sInstanceCount++:other.mValue) 
    { } 

    unsigned int value() const 
    { 
     return mValue; 
    } 

private: 
    static int sInstanceCount; 
    unsigned int mValue; 
    static unsigned int const Special = ~0U; 
}; 


int UniqueNumber::sInstanceCount(0); 


int main() 
{ 
    std::vector<UniqueNumber> numbers(10,UniqueNumber(false)); 
    for (size_t i = 0; i < numbers.size(); ++i) 
    { 
     std::cout << numbers[i].value() << " "; 
    } 
} 
+0

我不知道爲什麼您將額外的布爾參數添加到UniqueNumber的構造函數,但顯然,您的方法是最安全的(與其他命題相比)。 –

+0

布爾值是這樣用戶可以構造它獨特或特殊(一種是沒有價值的)。 –

+0

+1創造性 – StackedCrooked

4

有這樣做的兩種方式。

尼斯,和C++ 0x中的方式,是採取的初始化列表優勢:

std::vector<UniqueNumber> vec = { UniqueNumber(0), UniqueNumber(1) }; 

顯然,這裏的問題是,你必須指定出來爆滿。

在C++ 03,我會簡單地用一個循環:

std::vector<UniqueNumber> vec; 
vec.reserve(10); 
for (size_t i = 0; i != 10; ++i) { vec.push_back(UniqueNumber(i)); } 

當然,這也完全得到嵌入設計器功能:

template <typename ValueType, typename Generator> 
std::vector<ValueType> generateVector(size_t size, Generator generator) 
{ 
    std::vector<ValueType> vec; 
    vec.reserve(size); 
    for (size_t i = 0; i != size; ++i) { vec.push_back(generator()); } 
    return vec; 
} 

隨着NRVO踢,這是關於同樣的,它可以讓你指定自由創建的值。

同樣可以通過<algorithm>中的STL generate_n實現,並且我將包含lambda語法的感覺。

std::vector<ValueType> vec; 
size_t count = 0; 
std::generate_n(std::back_inserter(vec), 10, [&]() { return Foo(++count); }); 

在評論中提出@Eugen :)


注:WRT以「驚喜」,如果你想擁有獨特的元素,也許是一個vector是不是最合適的數據結構。如果你真的需要一個vector,我會考慮包裝到一個類中,以確保元素是唯一的,作爲一個不變量。

+0

毆打我,正要提出使用'std :: generate_n(std :: back_inserter(numbers),10,...);''''是一個「常規」的'CreateUniqueNumber'函數或lambda ... –

+0

@Eugen:啊,我想了一下已經看過這樣的構造,但不記得它是一個STL函數!當然,問題總是如何從一個簡單的「for」到一個冗長的表達式...... –

+0

我發現generate_n比一般的更具表現力,並且沒有更多的囉嗦, personal_opinion> –

相關問題