重载运算符以合并向量

时间:2011-12-04 09:41:30

标签: c++ vector operator-overloading std

我想在一个具有向量作为成员变量的类中重载operator +,以便执行两个不同对象的向量的合并。换句话说,我想要创建一个新对象,它具有一行中两个初始向量的向量元素作为向量。我尝试以下代码,我在operator +中收到有关std :: copy的错误。问题是什么?

class TestVector
{
    std::vector<int> myVector;

public:
    TestVector(){};
    TestVector(std::vector<int>);
    std::vector<int> getVector();
    TestVector operator +(TestVector);

};

std::vector<int> TestVector::getVector()
{
   return myVector;
}

TestVector TestVector::operator+(TestVector param)
{

    std::vector<int> tempVector;
    std::vector<int> paramVector = param.getVector();

    std::copy(paramVector.begin(), paramVector.end(), tempVector);
    std::copy(myVector.begin(), myVector.end(), tempVector.end());

    TestVector TestVector1(tempVector);

    return TestVector1;

}

此外,第二个复制语句是否有效合并两个向量?

更新:我在执行时遇到错误,说明迭代器在此语句中不兼容。怎么了?
    tempVector.insert(tempVector.end(),param.getVector()。begin(),param.getVector()。end());

3 个答案:

答案 0 :(得分:1)

std::copy的第三个参数必须是迭代器,而不是容器。您可以使用std::back_inserter

std::copy(paramVector.begin(), paramVector.end(), std::back_inserter(tempVector));

第二个副本将编译,因为std::end()返回一个迭代器,但它会中断,因为迭代器只是指向向量的末尾。 std::copy尝试分配向量时,它不会增长向量;它只会调用未定义的行为。同样,std::back_inserter解决了这个问题。

在任何情况下,您根本不需要std::copy,因为std::vector直接提供了必要的语义:

TestVector TestVector::operator+(const TestVector& v)
{
    std::vector<int> t(myVector);
    t.insert(t.end(), v.myVector.begin(), v.myVector.end());
    return TestVector(t);
}

请记住使用const &…来避免这么多的复制。例如,第二个构造函数不必要地复制输入向量,getVector()不必要地复制内部向量。

即使上面的解决方案至少复制一次临时向量,这可以通过专用构造函数来避免:

class TestVector
{
    std::vector<int> myVector;

public:
    TestVector() { }
    TestVector(const std::vector<int>& v) : myVector(v) { }
    const std::vector<int>& getVector() const { return myVector; }
    TestVector operator+(const TestVector& v) const {
        return TestVector(op_add(), *this, v);
    }

private:
    struct op_add { };
    TestVector(op_add, const TestVector& a, const TestVector& b) : myVector(a) {
        myVector.insert(myVector.end(), b.myVector.begin(), b.myVector.end());
    }
};

答案 1 :(得分:1)

std::copy的第三个参数应该是某种输出迭代器。最安全的用法是插入迭代器。在#include <iterator>之后,您应该能够执行以下操作:

std::copy(paramVector.begin(), paramVector.end(), std::back_inserter(tempVector));
std::copy(myVector.begin(), myVector.end(), std::back_inserter(tempVector));

std::back_inserter是一个辅助函数模板,可以为给定的容器创建适当的back_insert_iterator

另请注意,您正在制作大量副本。就个人而言,我会使operator+成为一个自由函数,并通过const引用获取参数。目前您的operator+是非常量的,因此只能在非常量向量上调用,并通过复制获取其第二个参数。如果宣布getVectorconst TestVector& getVector() const;,那么你可以做这样的事情。

TestVector operator+(const TestVector& lhs, const TestVector& rhs)
{
    std::vector<int> ret( lhs.getVector() );
    ret.insert( ret.end(), rhs.getVector().begin(), rhs.getVector().end() );
    return TempVector(ret);
}

答案 2 :(得分:1)

如果您要为您的类型实施operator+,我建议您同时将operator+=实现为成员函数,然后根据前一个运算符实现operator+

// As a public member function
TestVector& TestVector::operator+=( const TestVector& rhs ) {
   myVector.insert( myVector.end(), rhs.myVector.begin(), rhs.myVector.end();
   return *this;
}

TestVector operator+( TestVector lhs, const TestVector& rhs ) {
   lhs += rhs;
   return lhs;
}

优点是您只需要几行代码就可以免费获得新操作,它不需要友谊或提供类型内部细节的访问器,并且效率高(不需要复制)用户代码不需要维护左侧操作员的情况。同时,operator+的实现可以作为一个自由函数(关于类型的对称性--ie转换 1 )和高效(在C ++ 11编译器中)如果TestVector有一个移动构造函数,它将只复制每个元素一次,因为唯一的成员是一个可移动的向量;在C ++ 03中,在return语句中有一个额外的副本可以被deafult删除构建和交换)。

1 注意:您可能需要考虑明确TestVector( std::vector<int> const & ),以避免隐式转换为TestVector