我希望将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
调用每个元素的除法,但它会以某种方式反过来。
答案 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
将随着它的增长而动态分配,但是,有时候,通用性的交易速度可能是合适的。