2017-08-04 15 views
3

私はペアの配列を持っています。私は0、1または-1を作るためにこの配列のmemsetを使いたい。どうしたらいいですか?私たちはいつものように通常の手順ですか?memset C++でペアの配列

ペアと配列は次のとおりです。

std::pair<int, int> ar[100][100]; 
+8

あなたはC++で何かをmemsetすることはほとんどありません。イニシャライザを使用してください。 –

+0

あなたはペアの配列の配列を持っています。だから、あなたは、すべてのもの、またはペアの配列をmemsetしたいですか? – juanchopanza

+4

私たちがいつもしているように、これを1にする方法は? – melpomene

答えて

4

std::pairではありません)PODタイプではないものにmemsetを使用しないでください - 行うには、未定義の動作です(うまくいかないだろうそう)。

コンストラクタを持つクラスでは、これらのコンストラクタを呼び出す必要があります。memsetはそうしません。 PODデータメンバーを持たないクラスには、 - memsetというメンバのコンストラクタが必要です。

小さいアレイの場合は、代わりにaggregate initializationを使用できます。 大きな配列の場合は、ループを使用できます。 また、std::fillもあります。

また、コンパイル時にサイズがわかっている場合は、Cスタイルの配列に対してstd::arrayを使用することをお勧めします。そうでない場合は、std::vectorです。

+1

'std :: pair'は型でもありません。しかし、 'std :: pait 'のmemsetを使って正確に何が問題になっているか知ることは興味深いでしょう。 – juanchopanza

+0

@juanchopanza - 引用http://en.cppreference.com/w/cpp/string/byte/memset "オブジェクトがトリビュアコピー可能でない場合(スカラー、配列、またはC互換構造体など)、ビヘイビア定義されていません。 'std :: pair'は簡単にはコピーできません。 –

1

前述のように、ペアはPODではありません。

#include <tuple> 
#include <utility> 
#include <cstring> 

/* this is a POD */ 
using pair_matrix = int [100][100][2]; 

extern std::tuple<int, int> foo(); 
extern void bar(std::tuple<int&, int&>); 

int main() 
{ 
    pair_matrix m; 

    /* we can memset PODS */ 
    std::memset(std::addressof(m), sizeof(m), 0); 

    /* we can convert the 2-d array into a tuple easily */ 
    auto at = [&m](int x, int y) { 
     auto& a = m[y][x]; 
     return std::tie(a[0], a[1]); 
    }; 

    /* and manipulate as a tuple */ 
    at(10,10) = foo(); 
    bar(at(10,10)); 
} 

別の(おそらくよりロバストな)方法は、fill方法を有する多次元配列クラスの概念を発明することである:データは、ユーティリティの少ない損失でPODとして再構築することができるしかし

#include <tuple> 
#include <utility> 
#include <memory> 

template<class Type, std::size_t...Dimensions> struct dimension_view; 
template<class Type> struct dimension_view<Type> 
{ 
    static constexpr std::size_t extent = 1; 
    static constexpr std::size_t size() { return extent; } 
    static constexpr std::size_t storage_size = 1; 

    using storage_type = Type; 

    constexpr dimension_view(Type* data) : data_(data) {} 

    operator Type&() { return *data_; } 

    template<class Other> 
    constexpr Type& operator=(Other&& other) { 
     *data_ = std::forward<Other>(other); 
     return *data_; 
    } 

    storage_type* data_; 
}; 

template<class Type, std::size_t Dim, std::size_t...Rest> 
struct dimension_view<Type, Dim, Rest...> 
{ 
    using next = dimension_view<Type, Rest...>; 
    static constexpr std::size_t extent = Dim; 
    static constexpr std::size_t size() { return extent; } 
    static constexpr std::size_t storage_size = Dim * next::storage_size; 

    using storage_type = Type [storage_size]; 

    constexpr dimension_view(Type* data) : data_(data) {} 

    auto begin() -> Type* 
    { 
     return data_; 
    } 
    auto end() -> Type* 
    { 
     return std::addressof(data_[extent * next::storage_size]); 
    } 

    auto operator[](std::size_t i) { 
     return next(std::addressof(data_[i * next::storage_size])); 
    } 

    Type* data_ ; 
}; 

template<class T, std::size_t...Dims> 
struct multi_dimensional_array 
{ 
    using view_type = dimension_view<T, Dims...>; 
    using storage_type = typename view_type::storage_type; 

    template<class...Args, std::enable_if_t<std::is_nothrow_constructible<T, Args...>::value>* = nullptr> 
    constexpr multi_dimensional_array(Args&&...args) 
    { 
     for(auto&& store : data_) 
     { 
      new (std::addressof(store)) T (args...); 
     } 
    } 

    template<class...Args, std::enable_if_t<not std::is_nothrow_constructible<T, Args...>::value>* = nullptr> 
    multi_dimensional_array(Args&&...args) 
    { 
     auto count = std::size_t(0); 
     try { 
      for(auto&& store : data_) 
      { 
       new (std::addressof(store)) T (args...); 
       ++count; 
      } 
     } 
     catch(...) { 
      destroy(count); 
     } 
    } 

    /* delete copies for now */ 
    multi_dimensional_array(multi_dimensional_array const&) = delete; 
    multi_dimensional_array& operator=(multi_dimensional_array const&) = delete; 
    multi_dimensional_array(multi_dimensional_array &&) = delete; 
    multi_dimensional_array& operator=(multi_dimensional_array &&) = delete; 

    ~multi_dimensional_array() 
    { 
     destroy(view_type::storage_size); 
    } 

    void destroy(std::size_t last) 
    { 
     while(last--) { 
      reinterpret_cast<T*>(get_data()+last)->~T();  } 
    } 

    constexpr auto begin_storage() { 
     return view_type(get_data()).begin(); 
    } 

    constexpr auto end_storage() { 
     return view_type(get_data()).end(); 
    } 

    constexpr auto fill(T value) -> void 
    { 
     std::fill(begin_storage(), end_storage(), value); 
    } 

    constexpr auto operator[](std::size_t i) -> decltype(auto) { 
     return view_type(get_data())[i]; 
    } 

    constexpr T* get_data() { 
     return reinterpret_cast<T*>(data_); 
    } 

    std::aligned_storage_t<sizeof(T), alignof(T)> data_[view_type::storage_size]; 
}; 

using pair_matrix = multi_dimensional_array<std::pair<int, int>, 100, 100>; 


void force_view(pair_matrix&); 
void force_deref(std::pair<int, int>&); 
std::size_t getval(); 

int main() 
{ 
    /* create with initial values */ 
    pair_matrix m(std::make_pair(-1, 1)); 

    /* fill the entire multidimentional array */ 
    m.fill(std::make_pair(-1, -1)); 

    m[10][10] = std::make_pair(1,1); 

    /* force compiler to generate some code to exercise implementation */ 
    force_view(m); 
    force_deref(m[getval()][getval()]); 
} 
1

C++の方法は、memsetの代わりにstd::fillを使用することで、何かのように:

std::pair<int, int> ar[100][100]; 
std::fill(&ar[0][0], &ar[0][0] + 100 * 100, std::make_pair(-1, -1)); 
関連する問題