试图提供将整数类型std :: vector除以常量的运算符

时间:2016-12-21 01:51:57

标签: c++ vector

我希望将std::vector的所有元素乘以常量,与普通类型在C ++中执行的方式相同:当输入向量具有整数类型且浮动时,至少结果应为整数否则为点类型。

我找到了基于std::multiplies的乘法代码,并使用替换std::divides对其进行了修改。结果,代码工作但不按我想要的顺序:

#include <iostream>
#include <vector>
#include <algorithm>

// std::vector multiplication by constant
// http://codereview.stackexchange.com/questions/77546
template <class T, class Q>
    std::vector <T> operator*(const Q c, const std::vector<T> &A) {

    std::vector <T> R(A.size());
    std::transform(A.begin(), A.end(), R.begin(),
                 std::bind1st(std::multiplies<T>(),c));
    return R;
}

// My modification for division. There should be integer division
template <class T, class Q>
    std::vector <T> operator/(const std::vector<T> &A, const Q c) {

    std::vector <T> R(A.size());
    std::transform(A.begin(), A.end(), R.begin(),
                 std::bind1st(std::divides<T>(),c));
    return R;
}



int main() {

    std::vector<size_t> vec;
    vec.push_back(100);

    int d = 50;

    std::vector<size_t> vec2 = d*vec;        
    std::vector<size_t> vec3 = vec/d;        
    std::cout<<vec[0]<<" "<<vec2[0]<<" "<<vec3[0]<<std::endl;

    // The result is:
    // 100 5000 0

    size_t check = vec[0]/50;
    std::cout<<check<<std::endl;
    // Here the result is 2

    // But

    std::vector<double> vec_d;        
    vec_d.push_back(100.0);        
    vec_d = vec_d/50;        
    std::cout<<vec_d[0]<<std::endl;

    // And here the result is 0.5

    return 0;
}

如何正确编写操作符?我认为std::bind1st会为c调用每个元素的除法,但它会以某种方式反过来。

编辑:我知道我可以写一个循环,但我想为大数字做很多分歧,所以我希望它更快......

3 个答案:

答案 0 :(得分:3)

std::transform与C ++ 11一起使用,我建议制作一个lambda(参见this tutorial),而不是使用bind

std::transform(A.begin(), A.end(), R.begin(), [c](T val) {
    return val / c;
});

在我看来,lambdas几乎总是比bind更具可读性,特别是在(就像你的情况下)你没有绑定所有函数的参数时。

虽然如果你担心性能,原始的for循环可能会稍快一些,因为函数调用没有开销并且创建了lambda对象。

根据DietmarKühl的说法:

  

std::transform()可能会做一些“魔术”,实际上比循环表现更好。例如,当实现注意到它在连续的整数序列上使用时,实现可以选择对循环进行向量化。但是,它不太可能比循环慢。

答案 1 :(得分:1)

auto c_inverse= 1/c;
std::transform(A.begin(), A.end(), R.begin(), [c_inverse](T val) {
    return val * c_inverse;
});

与其他帖子类似,但应该提到的是,除了除法之外,你很可能会通过乘以逆来看到性能提升。

答案 2 :(得分:1)

为什么只为矢量而设?这是一种更通用的方法,可以使用多种类型的容器:

template <class container, class Q>
container operator/(const container& A, const Q c) {
    container R;
    std::transform(std::cbegin(A), std::cend(A), std::back_inserter(R),
        [c](const auto& val) {return val / c; });
    return R;
}

当然,预计它会比向量的预分配慢一点,因为back_inserter将随着它的增长而动态分配,但是,有时候,通用性的交易速度可能是合适的。