2013-05-13 12 views

Odpowiedz

29

To nie jest po prostu słaba praktyka, lecz:

  1. Wyciek pamięci (najprawdopodobniej, o ile nie używasz jakiś wzór, który nie jest widoczny z kodem, który podałeś), ponieważ obj zapisze kopię oryginalnego obiektu utworzonego przez wyrażenie new, a wskaźnik do tego obiektu zwróconego przez new zostanie utracony;
  2. Co najważniejsze, nieokreślone zachowanie nieokreślone zachowanie, ponieważ przechodzisz do delete wskaźnik do obiektu, który nie został przydzielony z new. Zgodnie z pkt 5.3.5/2 C++ 11 Standard:

[...] W pierwszej alternatywie (Delete Object), wartość argumentu z kasowania może być null pointer wartość, wskaźnik do obiektu nieszablonowego utworzonego przez poprzednie wyrażenie lub wskaźnik do podobiektu (1.8) reprezentujący klasę podstawową takiego obiektu (Klauzula 10). Jeśli nie, zachowanie jest niezdefiniowane.

+1

A druga trąbi pierwsza. Nie będzie przeciekał pamięci, ponieważ program prawdopodobnie nie będzie działał wystarczająco długo, aby mógł wykonać więcej niż jedną alokację. –

+0

@JamesKanze: Tak, rzeczywiście –

+1

Cóż, można przynajmniej "obj & x = * new". –

8

No i faktycznie prowadzi to do wycieku. x jest kopia zainicjowana, więc oryginalny obiekt wskazywany przez new obj został utracony.

Wystarczy użyć

obj x(...); 

Nie potrzeba dynamicznej alokacji. Lub

obj x = obj(...); 

jeśli musisz (zwątp się w to).

+2

Możesz też użyć referencji 'obj & = (* new ...' – Marcin

+0

@Marcin Możesz, ale dlaczego? –

+4

@Marcin tak, możesz ... Możesz również rozbić klawiaturę na ekranie. , nie znaczy, że powinieneś. :) –

7

Z pewnością nie; który kopiuje obiekt dynamiczny do zmiennej automatycznej, traci do niego wskaźnik, a następnie próbuje usunąć kopię automatyczną. Masz wyciek pamięci i nieprawidłowe usunięcie.

Znacznie lepiej byłoby użyć automatycznego zmiennej w pierwszej kolejności:

obj x(...); 
... 
// no need to delete anything 

lub, jeśli to naprawdę musi być dynamiczne z jakiegoś powodu (ponieważ jest zbyt duży na stosie, albo nie zawsze chcą go zniszczyć tutaj), a następnie użyć inteligentnego wskaźnika oraz odniesienie jeśli naprawdę nie lubią ->

std::unique_ptr<obj> p(new obj(...)); 
obj & x = *p; 
... 
// still no need to delete anything 

Zmiana swój x do odniesienia byłby ważny (tak długo, jak jesteś ostrożny, że wyjątki, wczesne zwracanie funkcji itp. nie będą spowodować wyciek), ale spowodowałoby to zamieszanie wśród wszystkich nieszczęśliwych, którzy musieliby go utrzymać.

0

Nie można poprawnie usunąć obiektu, jeśli robisz to w ten sposób.

Najpewniej wykonujesz następujące czynności.

class A 
{ 
public: 
    int test (void) { return 1; } 
}; 

int main (void) 
{ 
    A * p = new A; 
    A v(*p); 
    //... 
    delete &v; // &v != p and v is not constructed via new! 
    return 0; 
} 

Jeśli chcesz pracować z obiektową składnią, możesz powiązać odniesienie do obiektu.

class A 
{ 
public: 
    int test (void) { return 1; } 
}; 

int main (void) 
{ 
    A * p = new A; 
    A & r = *p; 
    int i = r.test(); 
    delete p; 
    return 0; 
} 

Jeśli usuniesz obiekt za pomocą tego samego wskaźnika, nie będzie wycieku.

Powiązane problemy