如何优化 C++ class 容器的加法运算符?
How can an addition operator for a C++ class container be optimized?
考虑
class abc
{
public:
map<int,double> data;
abc(map<int,double> && in):data(std::move(in)){}
abc operator + (const abc & in)
{
auto tmp = data;
for( auto & itr : in.data)
tmp[itr.first] += itr.second;
return abc(std::move(tmp));
}
};
我想更好的实现可能是
abc operator + (const abc & in)
{
auto &tmp1 = (data.size() > in.data.size() ? data : in.data);
auto &tmp2 = (data.size() > in.data.size() ? in.data : data);
auto tmp = tmp1;
for( auto & itr : tmp2)
tmp[itr.first] += itr.second;
return abc(std::move(tmp));
}
我想要实现的是,如果我有一个声明,例如,
S = A+B+C+D+E
并假设 B
、 C
和 D
为空成本应与
相同
S = A+E
如果 abc
类型为零,我基本上不想承担费用。有办法实现吗?
我认为你会做得更好:
abc operator + (abc lhs, const abc& rhs) // Note 'lhs' by value.
{
for(const auto & val : rhs.data)
lhs.data[val.first] += val.second;
return lhs; // Rely on NRVO
}
更喜欢按值获取参数的原因是,如果它是临时的(例如,A + B
的结果),则不需要副本。编译器可以直接传递临时文件。
编辑
WhiZTiM 建议的代理会更有效率,因为它将所有事情推迟到最后。它依赖于在完整表达式结束之前临时对象不会被销毁的事实。
struct Proxy
{
std::vector<const abc*> values;
operator abc() {
assert(values.size() > 2);
abc result = *(values.back()); // Can't avoid one copy.
values.pop_back();
for (const auto& v : values)
for (const auto& key_value : v->data)
result.data[key_value.first] += key_value.second;
return result;
}
};
Proxy operator +(const abc &lhs, const abc& rhs) {
Proxy result;
result.values.push_back(&lhs);
result.values.push_back(&rhs);
return result;
}
Proxy operator +(Proxy lhs, const abc& rhs) {
lhs.values.push_back(&rhs);
}
Proxy operator +(const abc& lhs, Proxy rhs) {
rhs.values.push_back(&lhs);
}
Proxy operator +(Proxy lhs, const Proxy& rhs) {
// implementation left as an exercise for the reader.
}
注意:以上未公开给编译器。
考虑
class abc
{
public:
map<int,double> data;
abc(map<int,double> && in):data(std::move(in)){}
abc operator + (const abc & in)
{
auto tmp = data;
for( auto & itr : in.data)
tmp[itr.first] += itr.second;
return abc(std::move(tmp));
}
};
我想更好的实现可能是
abc operator + (const abc & in)
{
auto &tmp1 = (data.size() > in.data.size() ? data : in.data);
auto &tmp2 = (data.size() > in.data.size() ? in.data : data);
auto tmp = tmp1;
for( auto & itr : tmp2)
tmp[itr.first] += itr.second;
return abc(std::move(tmp));
}
我想要实现的是,如果我有一个声明,例如,
S = A+B+C+D+E
并假设 B
、 C
和 D
为空成本应与
S = A+E
如果 abc
类型为零,我基本上不想承担费用。有办法实现吗?
我认为你会做得更好:
abc operator + (abc lhs, const abc& rhs) // Note 'lhs' by value.
{
for(const auto & val : rhs.data)
lhs.data[val.first] += val.second;
return lhs; // Rely on NRVO
}
更喜欢按值获取参数的原因是,如果它是临时的(例如,A + B
的结果),则不需要副本。编译器可以直接传递临时文件。
编辑 WhiZTiM 建议的代理会更有效率,因为它将所有事情推迟到最后。它依赖于在完整表达式结束之前临时对象不会被销毁的事实。
struct Proxy
{
std::vector<const abc*> values;
operator abc() {
assert(values.size() > 2);
abc result = *(values.back()); // Can't avoid one copy.
values.pop_back();
for (const auto& v : values)
for (const auto& key_value : v->data)
result.data[key_value.first] += key_value.second;
return result;
}
};
Proxy operator +(const abc &lhs, const abc& rhs) {
Proxy result;
result.values.push_back(&lhs);
result.values.push_back(&rhs);
return result;
}
Proxy operator +(Proxy lhs, const abc& rhs) {
lhs.values.push_back(&rhs);
}
Proxy operator +(const abc& lhs, Proxy rhs) {
rhs.values.push_back(&lhs);
}
Proxy operator +(Proxy lhs, const Proxy& rhs) {
// implementation left as an exercise for the reader.
}
注意:以上未公开给编译器。