为了显示问题,假设您有一个名为basic_ma的类,并且其成员是MultiArray( MA )。还假设在构造函数(或方法)中,您在临时 MA (此处称为tmp
)中进行了一些计算,并且您希望将tmp
的内容复制到ma
(此行为是理想的,我希望同时tmp
和ma
)。
// 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
};
现在考虑另一个成员是前一个类的类。
// 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;
};
当我使用带有两个参数的构造函数实例化group_ma
时,会出现断言问题:
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
:
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;
}
使用gcc version 6.2.1
编译:
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 :(得分: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_ma
成为basic_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;
}