2012-07-04 53 views
7

Tiêu đề về cơ bản nói lên tất cả, tôi tự hỏi khi nào các thành viên tĩnh của một lớp C++ được khởi tạo và khi chúng ra khỏi phạm vi.C++ Phạm vi biến thành viên tĩnh

Tôi cần điều này cho vấn đề sau. Tôi có nhiều đối tượng của một lớp Foo và mỗi đối tượng cần truy cập vào một tài nguyên, được đóng gói bởi một lớp Bar khác. Đồng bộ hóa không phải là một vấn đề, vì vậy tôi muốn tất cả các đối tượng chia sẻ cùng một cá thể Bar.

Tôi đang sử dụng một con trỏ được quản lý đơn giản để tính tham chiếu.

Tôi có thể làm như sau:

class Foo { 
private: 
    static managed_pointer<Bar> staticBar; 
public: 
    Foo() { 
     if(!staticBar) 
      staticBar = new Bar; 
    } 
    /* 
    * use staticBar in various non-static member functions 
    */ 
}; 

managed_pointer<Bar> Foo::staticBar = NULL; 

các managed_pointer staticBar nên xóa các đối tượng Bar ngay sau khi nó đi ra khỏi phạm vi - nhưng khi điều này xảy ra? khi trường hợp cuối cùng của Foo bị phá hủy? về thoát ứng dụng?

Cảm ơn lời khuyên của bạn!

+0

oops, cảm ơn bạn đã sửa lỗi đánh máy. – Pontomedon

+0

Ví dụ cuối cùng của Foo bị hủy khi bạn chỉ xóa phiên bản cuối cùng hoặc khi chương trình của bạn tồn tại. Một thành viên tĩnh của một lớp sẽ tồn tại cho dù có bao nhiêu phiên bản của lớp đó. – Gabi

Trả lời

13

static s và hình cầu được khởi tạo ngay trước khi chương trình bắt đầu (trước khi main được gọi, chương trình thực sự bắt đầu trước đó) và thoát khỏi phạm vi sau khi thoát khỏi main.

Ngoại lệ - số liệu thống kê cục bộ (biến tĩnh được khai báo bên trong hàm) và lớp mẫu không sử dụng static thành viên.

Không có gì liên quan đến số lượng phiên bản.

+0

Biến tĩnh cục bộ không được khởi tạo trước khi chương trình bắt đầu. – Gabi

+0

ok cảm ơn. Bạn có ý nghĩa gì bởi "Nó không liên quan gì đến số lượng cá thể"? Trường hợp của lớp Foo? – Pontomedon

+1

vâng nó không quan trọng bao nhiêu trường hợp của Foo có, tất cả họ sẽ chia sẻ Bar. –

2

Tiêu chuẩn không chỉ định thứ tự khởi tạo chính xác, nó được thực hiện cụ thể. Chúng sẽ được khởi tạo ngay từ đầu chương trình và được deallocated ở cuối.

Bạn phải rất cẩn thận với những gì bạn đang làm, bởi vì nếu bạn có một số đối tượng tĩnh khác dựa vào đối tượng này tồn tại, đó là UB. Không có lệnh cho thứ tự nào sẽ được khởi tạo.

Bạn có thể có thể nhìn vào một cái gì đó như tăng :: call_once để đảm bảo nó được khởi tạo một lần, nhưng tôi sẽ không dựa vào thứ tự các số liệu thống kê được khởi tạo.

Đối với tất cả những gì tôi biết, mã của bạn sẽ hoạt động, nhưng tôi đã bị vấn đề khởi tạo tĩnh cắn trước đó nên tôi muốn cảnh báo bạn.

EDIT: Cũng trong mã của bạn, khi managed_ptr sẽ nằm ngoài phạm vi (kết thúc chương trình), nó sẽ xóa bộ nhớ được cấp phát tự động. Nhưng bạn không nên làm bất cứ điều gì không tầm thường trong phá hủy của Bar vì bạn có thể kích hoạt UB bằng cách gọi vào các trường hợp free'd khác hoặc thậm chí mã đã bị xóa (vì nó đã xảy ra với tôi khi thư viện động đã bị xóa). Về cơ bản bạn đang ở trong một bãi mìn, vì vậy hãy cẩn thận.

+0

Tôi sẽ không có bất kỳ 'static' trong Foo, nhưng cảm ơn cho cảnh báo, một chi tiết tốt để có trong tâm trí. EDIT: cảm ơn bạn cũng cho cảnh báo thứ hai, tôi sẽ xem ra. – Pontomedon

+0

Ý tôi là, các đối tượng tĩnh khác trong chương trình * của bạn *. Nếu sau này bạn quyết định có một đối tượng khác, nói ReBar, đó cũng là tĩnh, và bạn nghĩ "hey tôi có thể gọi Bar :: Một cái gì đó vì nó tĩnh" bạn nên cẩn thận. –

+1

Ah, được rồi, tôi nghĩ tôi hiểu rõ vấn đề của bạn. – Pontomedon

1

Việc đầu tiên mà bật ra câu hỏi của bạn là quan niệm sai lầm phổ biến mà phạm viđời là những khái niệm tương đương. Họ không phải. Trong một số trường hợp như với các biến cục bộ, thời hạn được gắn với một ngữ cảnh cụ thể, nhưng điều đó không phải lúc nào cũng như vậy.

Một lớp tĩnh biến thành viên đã lớp phạm vi (nó có thể truy cập bất cứ nơi nào trong chương trình) và tĩnh đời, có nghĩa là nó sẽ được khởi tạo trong trật tự liên quan đến các biến tĩnh khác trong cùng đơn vị dịch và theo thứ tự chưa được xác định đối với các biến tĩnh khác trong các đơn vị dịch khác, trước chính số (báo trước: không cần thực hiện khởi chạy trước câu lệnh đầu tiên, nhưng được đảm bảo trước odr đầu tiên sử dụng biến).

+2

Biến thành viên lớp tĩnh có phạm vi _class_: nó chỉ hiển thị trong các ngữ cảnh nơi các tên được tìm kiếm trong lớp. Nó có tuổi thọ tĩnh, và ràng buộc bên ngoài (một khái niệm thứ ba mà mọi người đôi khi nhầm lẫn với hai bạn đề cập đến). Tuy nhiên, bạn đã đề cập đến điểm quan trọng: tuổi thọ và phạm vi là các khái niệm trực giao. (Ít nhất đến một mức độ. Có _are_ trường hợp mà phạm vi xác định tuổi thọ.) –

+0

@JamesKanze: đúng, sai lầm của tôi. Cảm ơn đã chỉ ra điều đó. –

Các vấn đề liên quan