van valami oka a két funkciót nem egyesítették funkciót?

szavazat
3

Az egyik legmagasabb szavazott kérdések alatt c ++ tag az úgynevezett „a szöveg feldarabolása C ++” . Ebben, a kérdező azt kérdezi: „Mi a legelegánsabb módja annak, hogy szét a húr C ++?”.

A legmagasabb szavazott válasz erre a kérdésre ad e két funkciója van:

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

Ezek a funkciók a munka nagy. De igyekszem megérteni, hogy miért a válaszoló nem összekapcsolják a két funkciót egy funkciót. Van némi teljesítményt, a használhatóságot és az olvashatóság előny, hogy én nem látom, hogy hagyja ki, ha kombinálja ezeket a funkciókat? Teljes program kombinált funkció az alábbi:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;    
// splitting them into two seperate functions is unnecessary it seems to me, and makes the underlying function harder to understand.
std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

int main()
{
    std::vector<std::string> x = split(one:two::three, ':');
    for (int i = 0; i<x.size(); ++i) cout << x[i] << '\n';
    return 0;
}

Találom ezt a funkciót szétválasztani, hogy rendkívül kevésbé elegáns - és nehezebb megérteni -, de úgy érzem, kell valami hiányzik. Miért nem csak össze őket?

A kérdést 01/04/2013 19:59
a forrás felhasználó
Más nyelveken...                            


2 válasz

szavazat
4

Képzeljük el, hogy fogsz szét egy csomó különböző forrásokból, de szeretné, hogy az eredmények minden végül egy tartályba. Az, hogy nem akarja a funkciót, hogy mindig hozzá egy új tartályt az Ön számára:

Mielőtt igényel plusz munkát:

std::vector<std::string> sources = /* populate */;

std::vector<std::string> results;

for (const auto& source : sources)
{
    auto result = split(source, ":");

    // or maintain a vector of vectors...yuck
    results.insert(std::make_move_iterator(result.begin()),
                   std::make_move_iterator(result.end()));
}

Után, egyszerű:

std::vector<std::string> sources = /* populate */;

std::vector<std::string> results;

for (const auto& source : sources)
{
    split(source, ":", results);
}

Vagy: elképzelni fogsz szét egy csomó különbség források, és a hatékonyság kívánt minimalizálni memóriafoglalási (a profiler szerint kiosztani túl sok van, például). Szóval újra ugyanazt a vektort újra és újra, hogy elkerüljék a későbbi memóriakiosztások után az első osztott.

Mielőtt lassú:

std::vector<std::string> sources = /* populate */;

for (const auto& source : sources)
{
    auto result = split(source, ":");

    process(result);
}

Miután jobb:

std::vector<std::string> sources = /* populate */;

std::vector<std::string> result;
for (const auto& source : sources)
{
    result.clear();
    split(source, ":", result);

    process(result);
}

Természetesen az egyszerűség, amelynél a tartály létre az Ön számára szép az általános helyzet, és mi könnyen újra általánosabb funkcióra, a második funkció alacsony költséggel.

Válaszolt 01/04/2013 20:01
a forrás felhasználó

szavazat
3

A kód kimásolt az eredeti két függvényt kissé eltérő szemantika. Az első hozzáteszi , hogy egy meglévő vektor a felosztásának eredményeként, míg a második, tetejére épült az első létrehoz egy új vektor csak azokat az elemeket ebből osztott .

Azáltal, hogy a két funkció akkor is kínál (azonos költség) két különböző viselkedések, amelyek megfelelnek a különböző igényeket különböző felhasználók számára. Ha egyesíteni őket egyetlen egy változatot, és egy felhasználó szükséges építeni egy listát az összes zsetont nyert felosztása több húrok, akkor létre kell hozni több vektort, és egyesíti őket.

Egy érdekes kicsit, nem igazán része a kérdést a design egy / két funkció, a tényleges megvalósítás. A második függvény kell végrehajtani:

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;

}

A különbség az, hogy ahelyett, hogy visszatért a referencia nyert hívó splitbelsőleg, vissza kell adnia a helyi változó közvetlenül. Ez a változás lehetővé teszi Nevezett visszatérési érték optimalizálása a helyi változó, eltávolítja a költségek a másolat * .

* A C ++ 11 akkor is használhatja return std::move(split(s,delim,elems));, így ugyanazt a viselkedést, de ehhez szükség több karakternél, és még egy lépés eltávolítása helyett az egész műveletet.

Válaszolt 01/04/2013 20:06
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more