容器铸造

Container casting

本文关键字:      更新时间:2023-10-16

我有两个类和我的转换方法:

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::transformstd::assignstd::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]);
    }
}

请注意,asizebsize的初始化是这样进行的,以防止出现混叠问题。此外,createFromA应该是一个成员函数,它直接初始化类成员,而不需要其他类复制/赋值。

相关文章:
  • 没有找到相关文章