初始化对结构中矩阵元素的引用
Initialize references to matrix element in struct
我有一个表示 3D 位置的结构。有时访问单个组件很方便,有时访问所有组件作为向量(物理向量不是 std::vector)很方便,我正在为此使用 Eigen 线性代数库。由于只有三个元素 (x, y, z) 并且永远只会是三个元素,因此具有三个 double&
的结构是否有任何问题,这些 double&
是指本征矩阵的元素?即:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition
{
EnuPosition(): pos(ColumnVector3::Zero()), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(double east, double north, double up): pos((ColumnVector3() << east, north, up).finished()),
east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const ColumnVector3& position): pos(position), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const EnuPosition& enu):pos(enu.pos), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition& operator=(const EnuPosition& enu)
{
this->pos = enu.pos;
return *this;
}
ColumnVector3 pos;
double& east;
double& north;
double& up;
};
在我能想到的用例中 -Wall -Wextra -pedantic
,它在 g++ 5.5 上没有警告编译得很好:
int main ()
{
EnuPosition enu{12.5, 34.2, 99.2};
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
ColumnVector3 x;
x << 2.0,3.0,4.0;
enu.pos = x;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::MatrixXd y;
y.resize(3,1);
y << 7.6,8.7,9.8;
enu.pos = y;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::Matrix<double,3,3> R;
enu.east = 1;
enu.north = 1;
enu.up = 1;
R << 1,2,3,4,5,6,7,8,9;
enu.pos = (R * enu.pos).eval();
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
EnuPosition enu2 = enu;
std::cout << "east: " << enu2.east
<< " north: " << enu2.north
<< " up: " << enu2.up
<< std::endl;
}
就像我说的,它有效,我只是好奇它是否合法并且不依赖于未定义的行为等。或者还有其他需要注意的问题?
添加复制分配后,您的代码应该是安全的。
但是,如果您可以在代码中编写 east()
而不是 east
,那么一个稍微更优雅的解决方案可能是这样的:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition : public ColumnVector3
{
EnuPosition(): ColumnVector3(ColumnVector3::Zero()) {}
EnuPosition(double east, double north, double up): ColumnVector3(east, north, up) {}
template<class X>
EnuPosition(const X& other): ColumnVector3(other) {}
double& east() {return this->x();}
double const& east() const {return this->x();}
double& north() {return this->y();}
double const& north() const {return this->y();}
double& up() {return this->z();}
double const& up() const {return this->z();}
};
如果你有意不想继承,你当然仍然可以将 ColumnVector3
存储为成员。
我有一个表示 3D 位置的结构。有时访问单个组件很方便,有时访问所有组件作为向量(物理向量不是 std::vector)很方便,我正在为此使用 Eigen 线性代数库。由于只有三个元素 (x, y, z) 并且永远只会是三个元素,因此具有三个 double&
的结构是否有任何问题,这些 double&
是指本征矩阵的元素?即:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition
{
EnuPosition(): pos(ColumnVector3::Zero()), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(double east, double north, double up): pos((ColumnVector3() << east, north, up).finished()),
east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const ColumnVector3& position): pos(position), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const EnuPosition& enu):pos(enu.pos), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition& operator=(const EnuPosition& enu)
{
this->pos = enu.pos;
return *this;
}
ColumnVector3 pos;
double& east;
double& north;
double& up;
};
在我能想到的用例中 -Wall -Wextra -pedantic
,它在 g++ 5.5 上没有警告编译得很好:
int main ()
{
EnuPosition enu{12.5, 34.2, 99.2};
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
ColumnVector3 x;
x << 2.0,3.0,4.0;
enu.pos = x;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::MatrixXd y;
y.resize(3,1);
y << 7.6,8.7,9.8;
enu.pos = y;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::Matrix<double,3,3> R;
enu.east = 1;
enu.north = 1;
enu.up = 1;
R << 1,2,3,4,5,6,7,8,9;
enu.pos = (R * enu.pos).eval();
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
EnuPosition enu2 = enu;
std::cout << "east: " << enu2.east
<< " north: " << enu2.north
<< " up: " << enu2.up
<< std::endl;
}
就像我说的,它有效,我只是好奇它是否合法并且不依赖于未定义的行为等。或者还有其他需要注意的问题?
添加复制分配后,您的代码应该是安全的。
但是,如果您可以在代码中编写 east()
而不是 east
,那么一个稍微更优雅的解决方案可能是这样的:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition : public ColumnVector3
{
EnuPosition(): ColumnVector3(ColumnVector3::Zero()) {}
EnuPosition(double east, double north, double up): ColumnVector3(east, north, up) {}
template<class X>
EnuPosition(const X& other): ColumnVector3(other) {}
double& east() {return this->x();}
double const& east() const {return this->x();}
double& north() {return this->y();}
double const& north() const {return this->y();}
double& up() {return this->z();}
double const& up() const {return this->z();}
};
如果你有意不想继承,你当然仍然可以将 ColumnVector3
存储为成员。