容器铸造
Container casting
我有两个类和我的转换方法:
class A;
class B;
class A
{
...
};
class B
{
...
static B fromA(A a)
{
B b;
// ... some property conversions from A to B
return b;
}
operator A()
{
// ... some property conversions from this(B) to A
return A
}
}
可以看出,我在类B中定义了一个强制转换(用于B->a)+一个静态转换(用于a->B)。禁止在类a中定义任何强制转换或转换。
假设我有两个向量:
vector<vector<A> > vecA; // pre-defined
vector<vector<B> > vecB; // to be casted from vecA
实现它们之间的数据转换的最佳(最快)方式是什么,而不是我丑陋的解决方案:
using namespace std;
vecB.resize(vecA.size());
for(int i = 0; i<vecA.size(); i++)
{
vecB[i].resize(vecA[i].size());
for(int j = 0; j<vecA[i].size(); j++)
{
vecB[i][j] = B::fromA(vecA[i][j]);
}
}
为B 定义运算符
B::operator=(const A& a)
{
// actual code to copy from a to b.
}
在您的代码中更改行
vecB[i][j] = B::fromA(vecA[i][j]);
至
vecB[i][j] = vecA[i][j];
它将消除许多临时A&在原始代码中创建的B对象。
另外,不要使用vecB[i][j],而是使用迭代器。以下代码可能有一些语法错误
vecB.resize(vecA.size());
vector<vector<A> >::const_iterator itA1;
vector<vector<B> >::const_iterator itB1;
vector<A> >::const_iterator itA2;
vector<B> >::const_iterator itB2;
for(itA1=vecA.begin(), itB1= vecB.begin();
itA1 != vecA.end();
++itA1, ++itB1)
{
for(itA2 = (*itA1).begin(), itB2=(*itB1).begin();
itA2 != (*itA1).end();
++itA2, ++itB2)
{
(*itB2) = *itA2;
}
}
如果您愿意,可以使用算法和迭代器,而不是手工制作的for
循环(如果您的标准库实现经过了大量优化,可能会更快一些),但核心复杂性保持不变-您必须单独转换每个元素,这是无法解决的。
您可以使用std::transform使代码更短、更易于阅读。但是,我认为如果您将方法B fromA(A a)
定义为一个接受B&
类型的输出参数的void方法,您将获得最佳性能。即,使您的方法声明static void fromA(const A&, B&)
。通过这种方式,对于c++11之前的代码,您将避免返回对象的副本。
或者,使方法fromA
实例方法而不是静态方法,并再次使其无效-该方法将修改当前实例。另一个选项正如其他答案中所指出的那样——创建一个以const A&
为唯一参数的B的构造函数。
您可以定义一个隐式转换构造函数来将A
转换为B
,而不是一个命名函数:
B(A const & a) {
// ... some property conversions from A to B
}
现在你可以用之类的东西转换单个矢量
std::vector<B> vecB(vecA.begin(), vecA.end()); // declare a new vector
vecB.assign(vecA.begin(), vecA.end()); // reassign an existing vector
您仍然需要一个循环来重新分配一个向量;也许类似于:
vecB.clear();
vecB.reserve(vecA.size());
for (auto const & vA : vecA) {
vecB.push_back(std::vector<B>(vA.begin(), vA.end()));
}
这并不比您的版本快,但需要编写更少的代码。
而不是定义:
static B fromA(A a);
定义:
B(A a)
作为转换构造函数
通常,使用explicit
关键字可以避免这种情况,但在这里,这似乎正是您想要的,因为您需要从构建B
这将简化
vecB[i][j] = B::fromA(vecA[i][j]);
至:
vecB[i][j] = vecA[i][j];
这看起来像是`std::copy
如果你想写漂亮的代码,你可以使用std::transform
、std::assign
或std::for_each
,但如果你想要快速的代码,那么很难写出比这更快的代码:
vecB.resize(vecA.size());
for (unsigned int i = 0, asize = vecA.size(); i < asize; i++)
{
const vector<A> & vin = vecA[i];
vector<A> & vout = vecB[i];
vout.resize(vin.size());
for (unsigned int j = 0, bsize = vout.size(); j < bsize; j++)
{
vout[j].createFromA(vin[j]);
}
}
请注意,asize
和bsize
的初始化是这样进行的,以防止出现混叠问题。此外,createFromA
应该是一个成员函数,它直接初始化类成员,而不需要其他类复制/赋值。
- 没有找到相关文章