2010-09-08 76 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; 
} 

Sẽ có một số "sử dụng sau khi miễn phí" lỗi trên molly->eatFood()?C++ - hàm trả về đối tượng

+0

Ví dụ này thiếu kiểu trả về cho makeCat(). – pascal

+0

Và nó có nhiều lỗi hơn. Nếu bạn muốn biết về một lỗi biên dịch thời gian, bạn nên đăng ít nhất là mã compilable. – sbi

+2

Kevin: đọc về STL auto_ptr và tăng shared_ptr. –

Trả lời

19

Corrected chương trình của bạn và tạo ra một thực hiện ví dụ về 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; 
} 

Nó sẽ tạo ra kết quả:

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

Tôi đề nghị bạn học một cuốn sách cơ bản về C++ bìa để trang trải trước khi tiếp tục .

+0

cảm ơn, Notinlist –

+3

... mặc dù nó có thể tạo ra một đầu ra khác nhau từ tiêu chuẩn C++ không yêu cầu một trình biên dịch để elide Vì vậy, nó hoàn toàn có thể nhìn thấy một hai "Cat Cat2 bị phá hủy" tin nhắn (không có RVO, ví dụ) – sellibitze

+0

'makeCat1' trả về một con trỏ, và' makeCat2' trả về một tham chiếu? – qed

3

Không có lỗi khi sử dụng bộ nhớ không hợp lệ ngoài rò rỉ bộ nhớ ở cuối chương trình của bạn. Nếu một cái gì đó được tạo ra trên heap (chẳng hạn như với new) thì bạn cần phải gọi delete để giải phóng nó.

Bạn cũng có nhiều lỗi cú pháp, được sửa dưới đây.

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

Có thể rò rỉ bộ nhớ khi chương trình chấm dứt không? – Eiko

+0

@Eiko: Thông thường, hệ điều hành sẽ miễn phí nhưng điều này không được đảm bảo. Đối với bất cứ điều gì mà không được bảo đảm nó rất không được khuyến khích để làm điều đó. Đặc biệt với bộ nhớ không giải phóng. Ví dụ, người nói rằng một đoạn mã quan trọng không tồn tại trong destructor. –

+0

Tôi đồng ý rằng nó khôn ngoan để dọn dẹp sau khi bạn - và với mã sạch nó không phải là công việc nhiều anyway. (Mặc dù đôi khi tôi đọc lời khuyên để không lãng phí những chu kỳ CPU) – Eiko

0

Tôi nghĩ rằng nó phải là Cat *ladyCat *molly, nhưng nếu không thì sẽ ổn.

+0

Khi tôi trả lại đối tượng ** sally **, không phải là giá trị truyền qua? Nếu có, sẽ không ** sally ** bị xóa sau khi chức năng kết thúc? –

+0

Nếu bằng 'sally', bạn có nghĩa là biến 'lady' bên trong makeCat, không. – MerickOWA

+0

Bạn thực sự vượt qua một con trỏ (nhưng bạn đã bỏ dấu "*" trong mã của mình. – Eiko

2

lady được tạo trên heap (với số new), nó sẽ không bị hủy khi bạn thoát phương thức makeCat. Vì vậy, các cuộc gọi trên molly là hoàn toàn hợp lệ.

NHƯNG, bạn bị rò rỉ bộ nhớ. Bạn cần xóa molly sau khi sử dụng nó (đôi khi trong tương lai.) Vì chương trình của bạn kết thúc, đây không phải là vấn đề lớn. Trong một chương trình lớn hơn, đây sẽ là một vấn đề rất lớn.

5

new Cat("fluffy") tạo con trỏ. Bạn sẽ cần phải chỉ định Cat* làm loại trả lại. Vì đối tượng được tạo trong heap, nó sẽ vẫn có sẵn sau khi hàm trả về.

+0

Nó vẫn có sẵn khi được tạo trên ngăn xếp khi nó được trả về theo giá trị (tức là sao chép được xây dựng lại (mặc dù trình biên dịch được phép tách bản sao) Vì vậy, ngoài các lỗi cú pháp mã là tốt như bằng văn bản và không sử dụng một đối tượng bị phá hủy –

2

Sự cố không phải là "Sử dụng sau khi miễn phí"; có lẽ bạn không xóa phiên bản mới.

0

Nếu trình biên dịch của bạn hỗ trợ C++ 11 bạn có thể sử dụng unique_ptr đây:

#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; 
} 

Bây giờ, bạn không cần phải lo lắng về việc xóa đối tượng được tạo ra. Nó sẽ bị xóa ngay sau khi con trỏ molly nằm ngoài phạm vi:

Cat created 
Cat is eating food 
Cat destroyed 
Các vấn đề liên quan