2017-01-24 7 views
0

считаютКак можно оптимизировать оператор сложения для контейнера класса C++?

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 тип равен нулю. Есть ли способ достичь этого?

+1

Да, вы используете тот факт, что временные объекты не уничтожаются до конца полного выражения. Таким образом, вы делаете 'operator + (..., ...)' возвращаете прокси-объект, который просто ссылается на объекты. Пусть прокси-серверы «concat-able» с самим собой и вашим объектом «operator + (..., ...)». В последнем назначении из последнего созданного прокси вы делаете дополнение одним махом из всех, с которыми связаны прокси ... – WhiZTiM

+0

@WhiZTim вы могли бы предоставить иллюстрацию или ссылку, чтобы показать эту технику? – user6386155

ответ

1

Я думаю, что вы будете делать лучше:

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. 
} 

Примечание: выше не подвергается воздействию компилятора.

+0

делает NRVO на аргументе функции? – user6386155

+0

Ах. Хорошая точка зрения. Возможно, нет. Стоит ли проверять вывод, хотя –

+0

будет 'std :: move' при возврате быть лучшей оптимизацией? – user6386155

Смежные вопросы