2010-09-08 27 views
11
// Assume class definition for Cat is here. 

Cat makeCat() { 
    Cat lady = new Cat("fluffy"); 
    return lady; 
} 

int main (...) { 
    Cat molly = makeCat(); 
    molly->eatFood(); 
    return 0; 
} 

Czy będzie „po użyciu wolnego” błędu na molly->eatFood()?C++ - funkcja, która zwraca obiekt

+0

W przykładzie brakuje typu zwracanego przez makeCat(). – pascal

+0

I ma więcej błędów. Jeśli chcesz wiedzieć o błędzie podczas kompilacji, powinieneś przynajmniej opublikować kod kompilacyjny. – sbi

+2

Kevin: przeczytaj o STL auto_ptr i boost shared_ptr. –

Odpowiedz

19

Poprawiono program i stworzył przykładową realizację class Cat:

#include <iostream> 
#include <string> 

class Cat { 
public: 
     Cat(const std::string& name_ = "Kitty") 
     : name(name_) 
     { 
       std::cout << "Cat " << name << " created." << std::endl; 
     } 
     ~Cat(){ 
       std::cout << "Cat " << name << " destroyed." << std::endl; 
     } 
     void eatFood(){ 
       std::cout << "Food eaten by cat named " << name << "." << std::endl; 
     } 
private: 
     std::string name; 
}; 

Cat* makeCat1() { 
     return new Cat("Cat1"); 
} 

Cat makeCat2() { 
     return Cat("Cat2"); 
} 

int main(){ 
     Cat kit = makeCat2(); 
     kit.eatFood(); 

     Cat *molly = makeCat1(); 
     molly->eatFood(); 
     delete molly; 

     return 0; 
} 

To będzie produkować wyjście:

Cat Cat2 created. 
Food eaten by cat named Cat2. 
Cat Cat1 created. 
Food eaten by cat named Cat1. 
Cat Cat1 destroyed. 
Cat Cat2 destroyed. 

proponuję nauczyć się podstawowej książki o C++ deski do deski przed kontynuowaniem .

+0

dzięki, Notinlist, –

+3

... chociaż może wytworzyć inne wyjście, ponieważ standard C++ nie wymaga kompilatora Tak więc, w miarę możliwości, możliwe jest zobaczenie kolejnych dwóch wiadomości "Cat Cat2 destroy" (na przykład brak RVO) – sellibitze

+0

'makeCat1' zwraca wskaźnik, a' makeCat2' zwraca referencję? – qed

3

Nie ma błędu w zakresie nieprawidłowego użycia pamięci innej niż wyciek pamięci na końcu programu. Jeśli coś jest tworzone na stercie (na przykład z new), musisz zadzwonić pod numer delete, aby go zwolnić.

Masz również wiele błędów składniowych, poprawionych poniżej.

Cat* makeCat() 
{ 
    Cat *lady = new Cat("fluffy"); 
    return lady; 
} 

int main (int argc, char** argv) 
{ 

    Cat* molly = makeCat(); 
    molly->eatFood(); 

    delete molly;//This was added 
    return 0; 
} 
+0

Czy można przeciec pamięć po zakończeniu programu? – Eiko

+0

@Eiko: Zwykle system operacyjny zwolni, ale nie jest to gwarantowane. W przypadku czegokolwiek, co nie jest gwarantowane, jest to wysoce niezalecane. Zwłaszcza jeśli nie zwalniasz pamięci. Na przykład, kto twierdzi, że ważny fragment kodu nie istnieje w destruktorze. –

+0

Zgadzam się, że mądrze jest posprzątać po sobie - i dzięki czystemu kodowi to i tak za mało. (Chociaż czasami czytam radę, aby nie marnować cykli procesora) – Eiko

0

myślę, że powinno być Cat *lady i Cat *molly, ale inaczej powinno być w porządku.

+0

Kiedy zwrócę obiekt ** Sally **, czy to nie jest wartość przekazywana? Jeśli tak, czy ** sally ** nie zostanie usunięte po zakończeniu funkcji? –

+0

Jeśli przez "Sally" masz na myśli zmienną "lady" wewnątrz makeCat, nie. – MerickOWA

+0

Rzeczywiście przekazujesz wskaźnik (ale brakowało ci "*" w kodzie – Eiko

2

Po utworzeniu lady na sterty (z new), nie zostanie ona zniszczona po wyjściu z metody makeCat. Dlatego połączenie pod numerem molly jest całkowicie poprawne.

ALE, masz wyciek pamięci. Musisz usunąć molly po użyciu (czasami w przyszłości). Ponieważ twój program się kończy, nie jest to wielka sprawa. W większym programie byłaby to bardzo ważna sprawa.

5

new Cat("fluffy") tworzy wskaźnik. Będziesz musiał określić Cat* jako typ zwracany. Ponieważ obiekt jest tworzony w stercie, będzie on nadal dostępny po zwróceniu funkcji.

+0

Jest on nadal dostępny, gdy zostanie utworzony na stosie, ponieważ jest zwracany przez wartość (tj. Kopia skonstruowana z powrotem (choć kompilator może usunąć tę kopię) Więc poza błędem składni kod jest w porządku, jak napisano i nie używa zniszczonego obiektu, –

2

Problem nie jest "Użyj po bezpłatny"; bardziej prawdopodobne, że nie usuwasz nowej instancji.

0

Jeśli kompilator obsługuje C++ 11 można użyć unique_ptr tutaj:

#include <iostream> 
#include <memory> 

using namespace std; 
class Cat { 
    public: 
     Cat() { 
      cout << "Cat created" << endl; 
     } 
     ~Cat() { 
      cout << "Cat destroyed" << endl; 
     } 
     void eatFood() { 
      cout << "Cat is eating food" << endl; 
     } 
}; 

unique_ptr<Cat> makeCat() { 
    unique_ptr<Cat> lady(new Cat); 
    return lady; 
} 

int main() { 
    unique_ptr<Cat> molly = makeCat(); 
    molly->eatFood(); 
    return 0; 
} 

Teraz nie trzeba się martwić o usunięcie utworzonego obiektu. Zostanie on usunięty, gdy tylko molowy wskaźnik wykracza poza zakres:

Cat created 
Cat is eating food 
Cat destroyed 
Powiązane problemy