Pomoc s funkcí v C++

pajon

Pomoc s funkcí v C++
« kdy: 30. 05. 2013, 20:23:36 »
Dobrý deň,

chcel by som sa spýtať, aký je rozdiel v nasledujúcich kódoch, konkrétne tá funkcia.

Kód: [Vybrat]
class mojaTrieda {
public:
    void a() {
      b = 0;
    }

private:
    int b;
}
}

a

Kód: [Vybrat]
class mojaTrieda {
public:
    void a():
        b(0) {

    }


private:
    int b;
}
}

Je to totožné alebo to má nejaký iný význam tá druhá definícia ?

Ďakujem :)
« Poslední změna: 30. 05. 2013, 21:46:33 od Petr Krčmář »


redbull

Re:Pomoc v c++
« Odpověď #1 kdy: 30. 05. 2013, 20:32:48 »
3 ukoncovacie zatvorky vtipne to neni

pajon

Re:Pomoc v c++
« Odpověď #2 kdy: 30. 05. 2013, 20:39:48 »
3 ukoncovacie zatvorky vtipne to neni

mám tam zátvorku na konci navyše, moja chyba. Ale ide o ten princíp

x14

  • ***
  • 182
    • Zobrazit profil
    • E-mail
Re:Pomoc v c++
« Odpověď #3 kdy: 30. 05. 2013, 20:45:48 »
Zde to ve výsledku dopadne stejně, ale pokud je členská proměnná objekt s konstruktorem s parametry, tak to nejde udělat jinak než druhým způsobem.

Sten

Re:Pomoc v c++
« Odpověď #4 kdy: 30. 05. 2013, 20:47:18 »
To druhé nepůjde zkompilovat, inicializace může být jenom v konstruktoru.


x14

  • ***
  • 182
    • Zobrazit profil
    • E-mail
Re:Pomoc v c++
« Odpověď #5 kdy: 30. 05. 2013, 21:10:32 »
Nojo, máš pravdu, úplně jsem přehlídl, že to není konstruktor :o

kozzi

Re:Pomoc v c++
« Odpověď #6 kdy: 30. 05. 2013, 21:20:10 »
Zde to ve výsledku dopadne stejně, ale pokud je členská proměnná objekt s konstruktorem s parametry, tak to nejde udělat jinak než druhým způsobem.

Tak nevim co tim myslis, ale imho je to blbost to co rikas.

Sten

Re:Pomoc v c++
« Odpověď #7 kdy: 30. 05. 2013, 22:08:50 »
Zde to ve výsledku dopadne stejně, ale pokud je členská proměnná objekt s konstruktorem s parametry, tak to nejde udělat jinak než druhým způsobem.

Tak nevim co tim myslis, ale imho je to blbost to co rikas.

„Nevím, co tím myslíš, ale je to špatně“ LOL

Je to víceméně správně. Pokud třída nemá konstruktor bez parametrů, musí mít členská proměnná takové třídy inicializátor.

Waseihou

Re:Pomoc s funkcí v C++
« Odpověď #8 kdy: 30. 05. 2013, 22:12:51 »
V tomto "studentském" případě bych doporučil kód si napsat, zkompilovat, a vyzkoušet co to dělá. Zkompilovat to samozřejmě nepůjde, ale asi jde o překlep a měl na mysli konstruktor. Rozdíl je v možnosti optimalizace, kdy pokud se hodnota uvede do inicializačního seznamu (za dvojtečku) tak kompilátor může lépe optimalizovat (někdy). V případě že by členská proměnná nebyl int ale například nějaký objekt který má defaultní konstruktor, tak v případě že by inicializace nastala až v těle konstruktoru (mezi { a }), tak by se nejdříve volal defautlní konstruktor pro ten objekt a pak by se inicializovala lokální isntance objektu a nakonec přes copy konstruktor by se nakopírovala do memebru.

#include <complex>

class MyClass{
  std::complex<double> m_x;
public:
   MyClass() // vola se defaultni konstruktor co to
   {
        // neoptimalni:
       m_x = std::complex<double>(1.234, 5.678); // vytvori novy komplexni cislo a prepise jim membera
   }
};

více:
http://www.cplusplus.com/forum/articles/17820/

x14

  • ***
  • 182
    • Zobrazit profil
    • E-mail
Re:Pomoc v c++
« Odpověď #9 kdy: 30. 05. 2013, 22:14:32 »
Zde to ve výsledku dopadne stejně, ale pokud je členská proměnná objekt s konstruktorem s parametry, tak to nejde udělat jinak než druhým způsobem.

Tak nevim co tim myslis, ale imho je to blbost to co rikas.

Tak nevím, co si myslíš, že si myslím, a co že je blbost...   ;)

Tak jinak - snažím se vysvětlit, k čemu je ta druhá konstrukce, takhle to vypadá, že k ničemu. Ano, u primitivních typů, jako je int v příkladu, je to jedno, ale pokud by ta členská proměnná byl nějaký objekt pouze s konstruktorem s parametry, tak nemám na výběr (no dobře, asi by to šlo zprasit přes placement delete/new :)). Obecně se inicializace 'seznamem' preferuje před inicializací přiřazením. Je univerzálnější a u objektů může být rychlejší. Klíčová slova: Member Initialization List Assignment

Opakuji, že jsem bohužel přehlédl, že funkce 'a' není konstruktor, teď se dívám, že je tam i void  :'( Vše výše uvedené platí samozřejmě pro konstruktor.

Sten

Re:Pomoc s funkcí v C++
« Odpověď #10 kdy: 30. 05. 2013, 23:00:36 »
V tomto "studentském" případě bych doporučil kód si napsat, zkompilovat, a vyzkoušet co to dělá. Zkompilovat to samozřejmě nepůjde, ale asi jde o překlep a měl na mysli konstruktor. Rozdíl je v možnosti optimalizace, kdy pokud se hodnota uvede do inicializačního seznamu (za dvojtečku) tak kompilátor může lépe optimalizovat (někdy). V případě že by členská proměnná nebyl int ale například nějaký objekt který má defaultní konstruktor, tak v případě že by inicializace nastala až v těle konstruktoru (mezi { a }), tak by se nejdříve volal defautlní konstruktor pro ten objekt a pak by se inicializovala lokální isntance objektu a nakonec přes copy konstruktor by se nakopírovala do memebru.

#include <complex>

class MyClass{
  std::complex<double> m_x;
public:
   MyClass() // vola se defaultni konstruktor co to
   {
        // neoptimalni:
       m_x = std::complex<double>(1.234, 5.678); // vytvori novy komplexni cislo a prepise jim membera
   }
};

více:
http://www.cplusplus.com/forum/articles/17820/

Tohle už kompilátory umí optimalizovat a ten defaultní konstruktor ani operátor přiřazení (nikoliv kopírovací konstruktor) by se nevolaly, akorát by kompilátor vyžadoval, aby defaultní konstruktor a operátor přiřazení byly dostupné (nemusí být ani implementované).

Jakub Galgonek

Re:Pomoc s funkcí v C++
« Odpověď #11 kdy: 31. 05. 2013, 00:15:20 »
Tohle už kompilátory umí optimalizovat a ten defaultní konstruktor ani operátor přiřazení (nikoliv kopírovací konstruktor) by se nevolaly, akorát by kompilátor vyžadoval, aby defaultní konstruktor a operátor přiřazení byly dostupné (nemusí být ani implementované).

Jsi si jistý? Co jsem to tak zkoušel, tak se nezdá, že by se něco z toho nevolalo. Jako jo, v některých situacích se defaultní konstruktor a operátor přiřazení vynechává, ale mám dojem, že toto není tento případ. Kdyby v té funkci bylo
std::complex<double> m_x = std::complex<double>(1.234, 5.678);
tak se opravdu zavolá jen kostruktor std::complex<double>(double, double).

Ivorne

Re:Pomoc s funkcí v C++
« Odpověď #12 kdy: 31. 05. 2013, 00:27:54 »
Tohle už kompilátory umí optimalizovat a ten defaultní konstruktor ani operátor přiřazení (nikoliv kopírovací konstruktor) by se nevolaly, akorát by kompilátor vyžadoval, aby defaultní konstruktor a operátor přiřazení byly dostupné (nemusí být ani implementované).

O optimalizacích toho moc nevím, ale to se mi nezdá, že by se prázdný konstruktor následovaný operátorem přiřazení vždy zoptimalizoval na kopírovací konstruktor. (jestli jsem tedy dobře pochopil, co jsi říkal)

Když budou prázdný konstruktor, kopírovací konstruktor i operátor přiřazení defaultní (automaticky vytvořené kompilátorem), tak se to zřejmě vyoptimalizuje. Ale když si to člověk napíše sám, tak přeci kompilátor nemůže vědět, jestli výsledek volání prázdného konstruktoru a přiřazovacího operátoru bude stejný jako výsledek volání kopírovacího konstruktoru. Sice by to nejspíše byla dost prasárna, ale optimalizátor tu není od toho, aby říkal, co je a není prasárna. Takže bych řekl, že v takovém případě k optimalizaci nedojde.

Sten

Re:Pomoc s funkcí v C++
« Odpověď #13 kdy: 31. 05. 2013, 00:51:06 »
Jsi si jistý? Co jsem to tak zkoušel, tak se nezdá, že by se něco z toho nevolalo. Jako jo, v některých situacích se defaultní konstruktor a operátor přiřazení vynechává, ale mám dojem, že toto není tento případ. Kdyby v té funkci bylo
std::complex<double> m_x = std::complex<double>(1.234, 5.678);
tak se opravdu zavolá jen kostruktor std::complex<double>(double, double).

Máš pravdu, v tomhle případě se to neoptimalizuje, protože to jsou dva různé příkazy, což by porušilo pravidlo „as-if“.

O optimalizacích toho moc nevím, ale to se mi nezdá, že by se prázdný konstruktor následovaný operátorem přiřazení vždy zoptimalizoval na kopírovací konstruktor. (jestli jsem tedy dobře pochopil, co jsi říkal)

Když budou prázdný konstruktor, kopírovací konstruktor i operátor přiřazení defaultní (automaticky vytvořené kompilátorem), tak se to zřejmě vyoptimalizuje. Ale když si to člověk napíše sám, tak přeci kompilátor nemůže vědět, jestli výsledek volání prázdného konstruktoru a přiřazovacího operátoru bude stejný jako výsledek volání kopírovacího konstruktoru. Sice by to nejspíše byla dost prasárna, ale optimalizátor tu není od toho, aby říkal, co je a není prasárna. Takže bych řekl, že v takovém případě k optimalizaci nedojde.

Je to závislé na pravidlech „as-if“ a RVO. Zjednodušeně řečeno, pokud je ten prázdný konstruktor a přiřazovací operátor součástí jednoho příkazu či je to v „return“, tak se to smí vyoptimalizovat, jinak ne:
Kód: [Vybrat]
#include <iostream>

class Test
{
public:
Test();
Test(const Test&);
Test(int i)
{}

Test& operator =(const Test&);
};


Test t()
{
// Tady se nevolá kopírovací konstruktor pro předání návratové hodnoty
Test ret(4);
std::cout << "Test" << std::endl;
return ret;
}


Test tt()
{
// Ani tady se nevolá kopírovací konstruktor pro předání návratové hodnoty
Test ret = t();
std::cout << "Test" << std::endl;
return ret;
}


int main()
{
/* Nezavolá se ani prázdný ani kopírovací konstruktor,
* přitom kompilátor neví, co se tam může dít, protože
* nejsou definované; stačí, že jsou dostupné */
Test test = tt();
return 0;
}

gamer

Re:Pomoc s funkcí v C++
« Odpověď #14 kdy: 31. 05. 2013, 01:43:30 »
Tady těm kopírovacím optimalizacím se říká copy elision a standard C++ celkem jasně specifikuje, kdy se to smí udělat:
http://en.wikipedia.org/wiki/Copy_elision
Jinak v C++11 je std::move, čímž se dá explicitně říct, že se má proměnná "přesunout" a nic se zbytečně nekopíruje.