2016-10-15 6 views
0

問題を表示するには、basic_maというクラスがあり、MultiArray(MA)というメンバーがあるとします。また、コンストラクタ(またはメソッド)で、MA(ここではtmpと呼ばれます)の計算があり、tmpの内容をmaにコピーしたいとします(この動作が望まれます。同じ時刻tmpおよびma)。クラスのメンバーとしてのBoost.MultiArray:サイズ変更およびコピーアサーションのクラッシュ

// A class with a MultiArray member 
class basic_ma { 
public: 
    basic_ma() { } 

    // initialize ma 
    basic_ma(size_t x, size_t y) { 
    // I would like to compute in tmp and then copy to member ma 
    array2d tmp(boost::extents[x][y]); 
    // dummy stuff, some serious calculation in real life 
    for(size_t i=0; i<tmp.shape()[0]; ++i) { 
     for(size_t j=0; j<tmp.shape()[1]; ++j) { 
     tmp[i][j] = (i+1.0)*(j+1.0); 
     } 
    } 
    ma.resize(boost::extents[tmp.shape()[0]][tmp.shape()[1]]); 
    ma = tmp; 
    // Alternative function to copy 
    //copy_ma(tmp, ma); 
    } 

    void show() { 
    cout << endl << "> Show ma" << endl; 
    for(size_t i = 0; i < ma.shape()[0]; ++i) { 
     cout << "> "; 
     for(size_t j = 0; j < ma.shape()[1]; ++j) { 
     cout << ma[i][j] << '\t'; 
     } 
     cout << endl; 
    } 
    cout << endl; 
    } 
private: 
    array2d ma;// MultiArray member 
}; 

メンバーが以前のクラスである別のクラスを検討してください。私は2つのパラメータを持つコンストラクタを使用してgroup_maをインスタンス化するとき

// Another class has several (possibly a vector of) basic_ma's 
class group_ma { 
public: 
    group_ma() { } 
    // constructs basic_ma's 
    group_ma(size_t x, size_t y) { 
    bma1 = basic_ma(x, y); 
    bma1.show(); 
    bma2 = basic_ma(y, x); 
    bma2.show(); 
    } 
private: 
    basic_ma bma1; 
    basic_ma bma2; 
}; 

そして、アサーションの問題が発生します。ここでは

a.out: /usr/include/boost/multi_array/multi_array_ref.hpp:484: boost::multi_array_ref<T, NumDims>& boost::multi_array_ref<T, NumDims>::operator=(const ConstMultiArray&) [with ConstMultiArray = boost::multi_array<double, 2ul>; T = double; long unsigned int NumDims = 2ul]: Assertion `std::equal(other.shape(),other.shape()+this->num_dimensions(), this->shape())' failed. 
Aborted (core dumped) 

mainです:

gcc version 6.2.1でコンパイル
int main(int argc, char **argv) { 

    basic_ma bma(3,5);// OK compile and run 
    bma.show();// OK compile and run 

    group_ma gma1;// OK compile and run 

    gma1 = group_ma(3, 3);// Compile but assertion error when running 

    group_ma gma2(4, 2);// Compile but assertion error when running 

    unique_ptr<group_ma> gma_ptr = unique_ptr<group_ma>(new group_ma(5, 6)); 
    // Compile but assertion error when running 

    return 0; 
} 

g++ main.cpp -std=gnu++11 -pedantic -Wall 

basic_maが問題なく動作し、group_maを使用すると問題が発生します。 私も同じ結果とMAさんをコピーするために別の機能を試してみました:私は私が間違ってやっているものを見ていない

// copy Boost.MultiArray source to dest 
void copy_ma(const array2d source, array2d& dest) { 
    vector<size_t> grid; 
    const size_t* shape = source.shape(); 
    grid.assign(shape, shape+source.num_dimensions()); 
    dest.resize(grid); 
    for(size_t i=0; i<source.shape()[0]; ++i) { 
    for(size_t j=0; j<source.shape()[1]; ++j) { 
     dest[i][j] = source[i][j]; 
    } 
    } 
} 

-DNDEBUGフラグを使用 は、メモリエラーが発生:malloc(): memory corruption (fast)

コード全体はここにある:

#include <iostream> 
#include <boost/multi_array.hpp> 
#include <memory> 

using namespace std; 

typedef boost::multi_array<double, 2> array2d; 

// A class with a MultiArray member 
class basic_ma { 
public: 
    basic_ma() { } 
    // initialize ma 
    basic_ma(size_t x, size_t y) { 
    // I would like to compute in tmp and the copy to member ma 
    array2d tmp(boost::extents[x][y]); 
    // dummy stuff 
    for(size_t i=0; i<tmp.shape()[0]; ++i) { 
     for(size_t j=0; j<tmp.shape()[1]; ++j) { 
     tmp[i][j] = (i+1.0)*(j+1.0); 
     } 
    } 
    ma.resize(boost::extents[tmp.shape()[0]][tmp.shape()[1]]); 
    ma = tmp; 
    // Alternative function to copy 
//  copy_ma(tmp, ma); 
    } 
    void show() { 
    cout << endl << "> Show ma" << endl; 
    for(size_t i = 0; i < ma.shape()[0]; ++i) { 
     cout << "> "; 
     for(size_t j = 0; j < ma.shape()[1]; ++j) { 
      cout << ma[i][j] << '\t'; 
     } 
     cout << endl; 
    } 
    cout << endl; 
    } 
private: 
    array2d ma;// MultiArray member 
}; 


// copy Boost.MultiArray source to dest 
void copy_ma(const array2d source, array2d& dest) { 
    vector<size_t> grid; 
    const size_t* shape = source.shape(); 
    grid.assign(shape, shape+source.num_dimensions()); 
    dest.resize(grid); 
    for(size_t i=0; i<source.shape()[0]; ++i) { 
    for(size_t j=0; j<source.shape()[1]; ++j) { 
     dest[i][j] = source[i][j]; 
    } 
    } 
} 

// Another class will have several (possibly a vector of) basic_ma's 
class group_ma { 
public: 
    group_ma() { } 
    // constructs basic_ma's 
    group_ma(size_t x, size_t y) { 
    bma1 = basic_ma(x, y); 
    bma1.show(); 
    bma2 = basic_ma(y, x); 
    bma2.show(); 
    } 
private: 
    basic_ma bma1; 
    basic_ma bma2; 
}; 

int main(int argc, char **argv) { 

    basic_ma bma(3,5);// OK compile and run 
    bma.show();// OK compile and run 

    group_ma gma1;// OK compile and run 

    gma1 = group_ma(3, 3);// Compile but assertion error when running 

    group_ma gma2(4, 2);// Compile but assertion error when running 

    unique_ptr<group_ma> gma_ptr = unique_ptr<group_ma>(new group_ma(5, 6)); 
    // Compile but assertion error when running 

    return 0; 
} 

答えて

0

エラーメッセージは、アレイが割り当て中に同じサイズではないことを述べています。それを修正するにはいくつかの方法があります。 group_maでのコンストラクタを使用します。

group_ma(size_t x, size_t y) 
    :bma1(x, y) 
    ,bma2(y, x) 
{ 
    //bma1 = basic_ma(x, y); 
    bma1.show(); 
    //bma2 = basic_ma(y, x); 
    bma2.show(); 
} 

デフォルトコンストラクタは、あなたの3x3を与えませんでした。 Boost docsでは、multi_arrayのサイズ変更について話しています。割り当てが必要な場合は、それを行うことができます。しかし、その次元は同じままであると警告します。

その後、basic_ma

void resize(size_t x, size_t y) 
{ 
    ma.resize(boost::extents[x][y]); 
} 

にメンバーを追加する:

basic_ma not_initialized; 
not_initialized.resize(3, 3); 
basic_ma bma(3,3); 
bma.show(); 
not_initialized= bma; // now this works 
not_initialized.show(); 

別の思考をしたい場合、あなたはそう...あなた自身の代入演算子に

をリサイズを行うことができますbasic_maは非公開です。 group_mabasic_maの友人にするそして、あなたはその後、この作品group_ma

void operator = (group_ma& source) 
{ 
    bma1.resize(source.bma1.ma.shape()[ 0 ], source.bma1.ma.shape()[ 1 ]); 
    bma2.resize(source.bma2.ma.shape()[ 0 ], source.bma2.ma.shape()[ 1 ]); 
    bma1= source.bma1; 
    bma2= source.bma2; 
} 

にこれを追加することができます:私は見ていないよう

group_ma gma1; 
gma1 = group_ma(3, 3); 
group_ma gma2(4, 2); 
gma1= gma2; 

より良い方法があるかもしれません、私は知りません。しかし、私はこれがあなたに合っていると思います。

あなたはグループの種類が異なる場合、さらに別の考えとより良い。代入演算子basic_maでサイズ変更を行います。グループ割り当てで必要なのは、

void operator = (group_ma& source) 
{ 
    bma1= source.bma1; 
    bma2= source.bma2; 
} 
+0

です。あなたが 'bma1 = basic_ma(x、y);を指摘したように'は動作しません。別の回避策は、移動代入演算子 'basic_ma&operator =(const basic_ma && other_bma)'を実装することです。私の具体的なアプリケーションでは、 'basic_ma'のコンストラクタを直接呼び出すことができないので、それはより適していると思います。しかし、まだ100%確実ではありません。 – Caos21

関連する問題