2012-05-16 5 views
7

Tôi có một lớp với một thành viên tĩnh đó là một con trỏ như sau:Khởi tạo một con trỏ tĩnh trong C++

animation.h

class Animation 
{ 
public: 
    Animation(); 
    static QString *m; 

}; 

animation.cpp

#include "animation.h" 

QString* Animation::m = 0; 

Animation::Animation() 
{ 
} 

Khi tôi cố gắng để khởi tạo con trỏ 'm' đó từ một lớp khác như vậy:

Animation::m = new QString("testing"); 

Nó hoạt động.

Nhưng khi tôi làm điều đó theo cách này:

QString x("Testing"); 
Animation::m = &x; 

Các chương trình bị treo.

Điều gì là sai với phương pháp thứ hai này?

Ngoài ra tôi muốn có con trỏ tĩnh đó là riêng tư để tôi có thể tạo các hàm getter và setter tĩnh cho nó. Setter nên sử dụng phương thức thứ hai là 'x' sẽ xuất hiện trong một tham số vì vậy tôi bị kẹt.

Cảm ơn bạn đã trợ giúp!

Trả lời

12

Tôi đặt cược nó không bị rơi trên dòng đó, nhưng sau đó.

Vấn đề là bạn đang lấy địa chỉ của một biến nằm trong bộ nhớ tự động và có thể thử truy cập vào nó sau đó. Biến số x sẽ bị hủy khi phạm vi kết thúc, nhưng Animation::m sẽ vẫn trỏ đến bộ nhớ đó (bộ nhớ bạn không còn sở hữu sau khi x hết phạm vi). Điều này dẫn đến hành vi không xác định.

Cũng giống như những điều sau đây sẽ là bất hợp pháp:

int* x = NULL; 
{ 
    int k = 3; 
    x = &k; 
} 
*x = 4; 

Cách giải quyết gán cho giá trị, không phải là con trỏ (với điều kiện nó trước đó đã được gán cho một giá trị QString*):

QString x("Testing"); 
*(Animation::m) = x; 
+0

Điều đó chắc chắn trả lời cảm ơn bạn! –

+0

'* (Animation :: m) = x;' gợi ý một con trỏ '0'. Con trỏ không bao giờ được cấp phát chỉ được khởi tạo thành' 0'. –

+0

@Lỗi bỏ lỡ điều đó, đã sửa. Cảm ơn. –

2

Điều gì là sai với phương pháp thứ hai này?

Lỗi treo vì bạn có nhiều khả năng truy cập vượt quá phạm vi trong đó x được tạo.

Biến tự động sẽ tự động bị hủy khi kiểm soát thoát khỏi phạm vi {} trong đó chúng được tạo, Vì vậy, ngoài phạm vi những gì bạn có là con trỏ trỏ đến dữ liệu không tồn tại. Việc truy cập dữ liệu này gây ra hành vi không xác định và sự cố.

Làm thế nào để đi về nó?

Bạn nên cấp phát bộ nhớ động và sau đó sao chép chuỗi vào con trỏ được phân bổ động để bạn có thể truy cập vào mọi nơi. Bằng cách này, chuỗi vẫn hợp lệ trừ khi và cho đến khi rõ ràng delete ed.

1

Tôi sẽ đặt cược rằng chương trình của bạn gặp sự cố khi bạn sử dụng Animation::m sau x đã bị hủy (có thể do phạm vi ngoài phạm vi).

Nếu bạn muốn sử dụng một setter để gán cho Animation::m, bạn sẽ cần phải vượt qua trong lập luận như một con trỏ hoặc bằng cách tham khảo:

class Animation 
{ 
public: 
    Animation(); 

    void set_m(QString* ptr) { 
     m = ptr; 
    } 

    void set_m(QString& ref) { 
     m = &ref; 
    } 

private: 
    static QString *m; 

}; 

Tuy nhiên, bạn vẫn sẽ cần phải chắc chắn rằng bất cứ điều gì m điểm vẫn còn sống khi bạn cố gắng sử dụng m.