Inicializace .., který z nich je účinnější?

hlasů
8

Mám následující otázku. Nichž jeden z nich je lepší, že by měly být dodržovány, a proč?

string strMyString = SampleString;

nebo

string strMyString(SampleString);

Díky předem.

Položena 12/03/2009 v 04:29
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
19

Odpověděl jsem to tady

Jedna věc, kterou jsem dal do této odpovědi zde: Ani se pomocí libovolného operátoru přiřazení .

Krátké vysvětlení pro smyčcový konkrétní věc ačkoli. std::stringmá konstruktor bere jeden argument, který přijímá char const*:

// simplified to a normal class declaration. std::string actually
// is a template instantiation. 
class string {
public:
    string(char const* str) {
        // copy over...
    }
};

Nyní můžete vidět, že má konstruktor, přičemž ukazatel na znak (y). Tak, aby mohl přijímat řetězec doslovný. Myslím, že následující případ tedy zřejmé:

string s("hello");

Bude volat konstruktor přímo a inicializovat stím. Tento jev se nazývá přímé inicializace .

Jiný způsob inicializace proměnné se nazývá kopie inicializace . Standard uvádí pro případ inicializace kopírování, kde má Inicializátor není typ objektu je inicializace, Inicializátor se převede do správného typu.

// uses copy initialization
string s = "hello";

Za prvé, pojďme uvést typy

  • s Má typ std :: string
  • "hello"je pole, které je v tomto případě opět se zachází jako ukazatel. Budeme pro ně je považovat char const*.

Překladač hledá dva způsoby, jak dělat svou konverzi.

  • Existuje konverzní konstruktor v std :: string?
  • Má inicializátor má typ, který má funkci operátor převod návratem std::string?

To bude vytvořit dočasný std::stringjedním z těchto způsobů, které se pak používají k inicializaci objektu spomocí std::string‚s kopírovací konstruktor . A vidí std::string je konverzní konstruktor, který přijímá inicializátor. Tak to ho používá. Na konci, to je v podstatě stejná jako

std::string s(std::string("hello"));

Všimněte si, že formulář, který se používá v příkladu, který spustil všechno,

std::string s = "hello";

definuje implicitní převod . Můžete označit konstruktor Vezmeme-li char const*jako explicitní pro typy, pokud by vás zajímalo, o pravidlech inicializace pro své věci, a to nedovolí použít odpovídající konstruktor jako konverzní konstruktoru už:

class string {
public:
    explicit string(char const* str) {
        // copy over...
    }
};

S tím, jeho inicializaci pomocí copy initializationa char const*ve skutečnosti je nyní (av různých jiných místech) zakázáno!

Nyní, že byl-li kompilátor nepodporuje vynechání z provizoria na různých místech. Překladač se nechá předpokládat, že kopii konstruktor kopie v této souvislosti, a může eliminovat nadbytečné kopie dočasné řetězce, a místo toho postavit dočasnou std :: string přímo do inicializační objekt. Nicméně, kopie konstruktor musí být přístupné zejména. Takže, inicializace kopie je neplatný, pokud to budete dělat

class string {
public:
    explicit string(char const* str) {
        // copy over...
    }

private: // ugg can't call it. it's private!
    string(string const&);
};

Teď vlastně pouze přímé inicializace případ je platný.

Odpovězeno 12/03/2009 v 04:36
zdroj uživatelem

hlasů
7

Kompilace oba, podívejte se na assembler. Prvním z nich je jeden méně instrukce ...

; 9    :    std::string f("Hello");

    push    OFFSET ??_C@_05COLMCDPH@Hello?$AA@
    lea ecx, DWORD PTR _f$[esp+80]
    call    DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z

; 10   :    std::string g = "Hello";

    push    OFFSET ??_C@_05COLMCDPH@Hello?$AA@
    lea ecx, DWORD PTR _g$[esp+80]
    mov DWORD PTR __$EHRec$[esp+88], 0
    call    DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z

... ale to je artefakt, protože to byl první kompilátor pila. Změňte kód tím, že vymění pořadí:

; 9    :    std::string g1 = "Hello";

    push    OFFSET ??_C@_05COLMCDPH@Hello?$AA@
    lea ecx, DWORD PTR _g1$[esp+136]
    call    DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z

; 10   :    std::string f1("Hello");

    push    OFFSET ??_C@_05COLMCDPH@Hello?$AA@
    lea ecx, DWORD PTR _f1$[esp+136]
    mov DWORD PTR __$EHRec$[esp+144], 0
    call    DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z

... a hle je druhý je jeden méně instrukce.

Také vidíme, že tento překladač (Microsoft VC ++ 2005, nastavení Release) generovaný stejný assembler pro obě verze. Takže nezáleží na tom, v tomto kompilátoru, a to dokázat.

Odpovězeno 12/03/2009 v 05:14
zdroj uživatelem

hlasů
2

Jediný skutečný rozdíl je, že první, kdo technicky vyžaduje použití kopírovacího konstruktoru, ale kompilátor nemá to Elide takže účinnost bude v obou případech totožné.

Avšak nejprve vyžaduje, aby kopie konstruktor být přístupná (tedy ne soukromé), a to iv případě, že není ve skutečnosti používá.

Odpovězeno 12/03/2009 v 04:54
zdroj uživatelem

hlasů
1

Ostatní odpovědi jsou správné, ale prosím také na paměti, že to asi nevadí. Bude to být vzácné, velmi vzácné, neuvěřitelně vzácné, bude, že účinnost řetězec inicializace někdy ovlivnit rychlost vašeho programu ani o zlomek vteřiny.

Samotná otázka je zábavná jedno, protože to pomáhá ukázat operace C ++ konstruktérů a úkolů, ale v praxi, pokud trávíte čas se snaží optimalizovat tento (a vyvěšením na SO je dost, jsou důkazem ..) jste opravdu naklápěcí u větrných elektráren.

Je lepší, aby se zabránilo rozptýlení a strávit svou snahu jinde.

Odpovězeno 12/03/2009 v 09:09
zdroj uživatelem

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