2014-02-24 83 views
10

下面的代碼工作,但我想避免的警告:填充的std ::數組中的成員初始化列表

警告:「健身:: vect_」應該在 成員初始化列表中被初始化[ -WeffC++]

當它與g++ -Weffc++開關編譯:

#include <array> 

template<class T, unsigned N> 
class fitness 
{ 
public: 
    explicit fitness(T v) 
    { 
    static_assert(N, "fitness zero length"); 

    vect_.fill(v); 
    } 

private: 
    std::array<T, N> vect_; 
}; 

int main() 
{ 
    fitness<double, 4> f(-1000.0); 

    return 0; 
} 

我應該忽略警告?有沒有辦法在構造函數初始化列表中填寫vect_(不更改其類型)?

+2

這是不容易填滿它,但你可以將其初始化爲'VECT _()'或'VECT _ {}'。 – juanchopanza

回答

1

,其產生filled_array應當具有它的返回值被省略的函數:

template<unsigned N, typename T> 
std::array<T, N> filled_array_sized(T const& t) { 
    std::array<T, N> retval; 
    retval.fill(t); 
    return retval; 
} 

但需要,傳遞至少大小N如果不是型號爲T

template<typename T> 
struct array_filler { 
    T && t; 
    template<typename U, unsigned N> 
    operator std::array<U, N>()&& { 
    return filled_array_sized<N, U>(std::forward<T>(t)); 
    } 
    array_filler(T&& in):t(std::forward<T>(in)) {} 
}; 
template<typename T> 
array_filler<T> 
filled_array(T&& t) { 
    return array_filler<T>(t); 
} 

注意,存儲在autofilled_array返回值是不明智的。

用途:

#include <array> 

template<class T, unsigned N> 
class fitness 
{ 
public: 
    explicit fitness(T v): vect_(filled_array(std::move(v))) { 
    //... 
    } 
//... 

我不知道,如果上面的代碼將產生的filled_array_size實施警告,但如果這樣做,本地禁用警告。

+0

你可以通過利用'fill'接受一個'const T'的事實來簡化這一點。無論如何,當元素將被複制時,它並沒有真正添加任何東西來完成所有的轉發。 –

+0

@StuartOlsen是真實的,但'fill'最終可以用一個右值版本來改進,該版本將第一個N和'移動'複製到最後一個! ...好吧,這是相當邊緣的。 – Yakk

+0

@StuartOlsen我利用了'const&',但由於'array'和初始化類型(在'filled_array'情況下我無法知道,因爲我們沒有訪問數組類型的類型不兼容直到後來),我必須做轉體操,直到我達到'filled_array_sized'。請注意,以上內容廣泛地依賴於RVO和NRVO的效率。 – Yakk

4

我相信你可以忽略這個警告。

如果你把一個空的初始化構造函數中的數組它的工作原理:

#include <array> 

template<class T, unsigned N> 
class fitness 
{ 
public: 
    explicit fitness(T v): 
    vect_{} 
    { 
    static_assert(N, "fitness zero length"); 

    vect_.fill(v); 
    } 

private: 
    std::array<T, N> vect_; 
}; 

int main() 
{ 
    fitness<double, 4> f(-1000.0); 

    return 0; 
} 
2

嘗試使用

explicit fitness(T v) : vect_{} 
{ 
//... 
} 
2

默認構造函數(讀:值初始化),應在此正常工作案件。由於std::array是一個聚合類型,它的元素將被每個值初始化,對於數字類型如double意味着零初始化,然後您可以使用fill

explicit fitness(T v) : vect_() // or vect_{} 
{ 
    vect_.fill(v); 
} 

你可能會更好使用std::vector和其填充構造函數,如果你不想做的基本上是翻倍的初始化,雖然。然後你的類將成爲:

template<class T> 
class fitness 
{ 
public: 
    explicit fitness(T v, unsigned n) : vect_(n, v) 

private: 
    std::vector<T> vect_; 
}; 

int main() 
{ 
    fitness<double> f(-1000.0, 4); 

    return 0; 
} 

你可以,當然,仍然保持N作爲模板參數,但有沒有必要做這樣的長度並不需要在編譯時是已知的。 (另一方面,如果你堅持使用std::array,你可能可以將構造函數設置爲constexpr,雖然這可能需要一些模板函數或者一個輔助constexpr函數,它返回一個初始化器列表才能正常工作,但我沒有玩過周圍足以與C++ 11個概念知道)

+0

最初我使用了一個std :: vector,但std :: array證明可以提供更好的性能(健身類對於我的框架來說至關重要)。我將檢查編譯器是否能夠避免雙重初始化。 – manlio

+0

...因爲std :: array是一個聚合,默認構造不會使內存爲零,但會使其未初始化(因此不需要雙重初始化)。 – manlio

+0

對於向量顯着慢於​​數組的情況很少見,如果正確使用它。 –

1

這裏的另一種方式,清潔恕我直言,使用C++11 non-static data member initializers

#include <array> 

template<class T, unsigned N> 
class fitness 
{ 
public: 
    explicit fitness(T v) 
    { 
    static_assert(N, "fitness zero length"); 

    vect_.fill(v); 
    } 

private: 
    std::array<T, N> vect_ { }; 
}; 

int main() 
{ 
    fitness<double, 4> f(-1000.0); 

    return 0; 
} 
相關問題