Mám inicializaci mé C ++ referenční proměnné správně?

hlasů
16

Snažil jsem se Google tento problém, a nemůžu najít nic, co považuji za důležité. Takže jsem třeba hledat špatnou věc; nicméně, ocenil bych poradit ...

Foobar &foobar = *new Foobar(someArg, anotherArg);

Zdá se mi to, nebo to, že se zdá páchnoucí?

Chápu, že newklíčové slovo je určen pro použití s ukazateli (jako takový):

Foobar *foobar = new Foobar(someArg, anotherArg);

Ale co když se nevyžadují ukazatel na instanci, a chtěli byste, aby místo toho použít odkaz? Nebo je to pravda, že nemusíte ji (podobně jako lokální proměnné) explicitně inicializovat; a pokud tomu tak je, co když chci inicializovat s parametry?

Vkládá nefunguje (pokud dělám něco špatného):

// the last argument is of type: int
Foobar &foobar(someArg, anotherArg);

... dává chyba kompilátoru:

Seznam inicializátoru exprese považovány za sloučeniny expresní neplatné inicializace non-const odkazu typu ‚foobar &‘ z dočasné typu ‚int‘

A také to nevypadá, že práce:

Foobar &foobar = Foobar(someArg, anotherArg);

... dává chyba kompilátoru:

Chyba: neplatný inicializace of non-const odkazu typu 'foobar &' z dočasné typu 'foobar'

Aktualizace 1:

Holé na paměti, že se vracím tuto hodnotu, takže nechci používat lokální proměnné; Chci použít hodnotu na haldě, ne zásobníku:

Foobar &helloWorld()
{
    Foobar &foobar = *new Foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

Měl bych být jen pomocí ukazatelů místo, nebo je to naprosto platný?

Položena 15/04/2009 v 17:13
zdroj uživatelem
V jiných jazycích...                            


6 odpovědí

hlasů
10

Proč si myslíte, že budete muset použít nové a odkazy na všechny? Proč ne:

Foobar foobar(someArg, anotherArg);

Pro vaše funkce - vrací hodnotu:

Foobar helloWorld()
{
    Foobar foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

nebo ukazatel:

Foobar * helloWorld()
{
    Foobar * foobar = new Foobar(someArg, anotherArg);
    foobar->HelloWorld();
    return foobar;
}

Pokud tak učiníte - volající je zodpovědný za smazání přidělenou objektu v určitém okamžiku.

Návrat z nečlenské funkce je jediné místo, kde lze obvykle nelze použít odkazy rozumně, jako věc, kterou by chtěl odkázat na většinou již neexistuje.

Odpovězeno 15/04/2009 v 17:17
zdroj uživatelem

hlasů
5

Ano, to je páchnoucí!

Pokud jste ‚nové‘ cosi, přiřadit ji na ukazatel (nebo typu smart-pointer), jak to bude nutné znovu odstranit, aby nedošlo k úniku paměti. Odkazy nejsou běžně považované za věci, které potřebujete, aby znovu odstranit, takže pokud někdo vidí tento kód (přiřazením new'ed objekt reference), může se snadno splést.

Můžete dělat...

const Foobar &foobar = Foobar(someArg, anotherArg);

... pokud opravdu chcete reference. Všimněte si, že jakmile foobar přejde mimo rozsah, je dočasný objekt, který odkazuje zemře. Ale tam není dost místa písemně upozornit, že když můžete přímým směrem dopředu zápis:

Foobar foobar(someArg, anotherArg);

Pravděpodobně nemáte skutečně potřebují reference ... jsou obvykle (ale ne výhradně) používán pro typy metod argumentů. To je tak, že můžete předat něco, co vypadá jako objekt, ale má pouze velikost ukazatele, a které tato metoda může změnit. Tato žádost byla zavedena především umožňují psát kopírovací konstruktor (nebudu vysvětlovat, že zde!).

Odpovězeno 15/04/2009 v 17:21
zdroj uživatelem

hlasů
3

Odkazy v C ++ jsou opravdu není tak silný, jak lidé očekávat, že budou, myslím, že zmatek pochází od lidí, kteří jsou zvyklí na jazyky, jako je Java a C #, které nemají ukazatele a mají odkazy, které mohou být přeřazení a používány.

Odkaz v C ++ je obecně nejlepší používat jako alias pro proměnné, takže si můžete zjednodušit věci, jako je předávání parametrů a návratové hodnoty. Existuje jen velmi málo situací, kdy byste se pokusit získat odkazem na způsob, jakým děláte na prvním řádku. Takže obvykle nemusíte dělat to, co se zdá, že se snažíte dělat :)

Druhý řádek je samozřejmě správné, a co můžete udělat něco jako návrat * foobar z funkce, která vrací referenci.

Odpovězeno 15/04/2009 v 17:18
zdroj uživatelem

hlasů
2

Vaše psaní správně. Ale mějte na paměti jeho podivné uvolnit ptr tím odstranit & refVar; (Může to být zaměněny za proměnnou, která nebyla vytvořen nový).

Byste měli vyzkoušet GotW pro osvědčené postupy procházející kolem http://www.gotw.ca/gotw/ I dont pamatovat, které lekce bylo to (tam byl více než jeden), ale čtení přes to je cennější než kdokoliv uvědomil (Gotchas bude méně překvapení)

Měli byste se pokusit psaní kódu, který nikdy nepoužívejte ukazatelů. Dělám to jen jednou zasekl, když jsem potřeboval kontejner BaseObj. Nebylo pracovní kolem toho. Obvykle jsem použil STL nádoby a mají nejvíce variabilní naživu v zásobníku {MyClass myVar; ...} nebo jako člen a předat ji kolem podle potřeby.

Jeho klidné snadno odstranit odkazy, jakmile začnete předání odkazu namísto ukazatele a používání stl nádob namísto nového. Všimněte si, že jsem nikdy použít auto_ptr. vektoru, string, deque, seznam a mapa by měla dělat většinu z toho, co budete potřebovat. Existují i ​​jiné nádoby.

Odpovězeno 15/04/2009 v 17:29
zdroj uživatelem

hlasů
1

Já bych doporučil používat inteligentní ukazatel. Musíte spravovat vlastnictví, a referenční nebude dělat za vás. Ve skutečnosti to bude zakrývat volajícímu, že existuje nějaký problém vlastnictví vůbec. Jako Scott Langham je uvedeno v komentáři, std :: auto_ptr bude fungovat. Používání shared_ptr od Boost, nebo TR1 může být lepší nápad.

boost::shared_ptr<Foobar> helloWorld()
{
    boost::shared_ptr<Foobar> foobar(new Foobar(someArg, anotherArg));
    foobar->HelloWorld();
    return foobar;
}
Odpovězeno 15/04/2009 v 17:40
zdroj uživatelem

hlasů
1

Ne, máš to. Foo a „body“ skutečný objekt, takže opravdu chtějí odkaz foo musíte dereference ukazatel foo, pokud jste.

@Neil má pravdu, i když - syntakticky to, jak se dostat to, co chcete, ale proč to chceš?

Odpovězeno 15/04/2009 v 17:18
zdroj uživatelem

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