2013-03-29 13 views
16

Cảnh báo Clang (khi sử dụng -Weverything hoặc Wglobal-constructors) về các hàm tạo đối với các đối tượng tĩnh.Làm thế nào để đối phó với cảnh báo toàn cầu-constructor trong clang?

warning: declaration requires a global constructor 
     [-Wglobal-constructors] 
A A::my_A; // triggers said warning 
    ^~~~ 

Tại sao điều này có liên quan và cách xử lý cảnh báo này?

Simple mã ví dụ:

class A { 
    // ... 
    static A my_A; 
    A(); 
}; 

A A::my_A; // triggers said warning 
+2

Chúng ta có thể thấy cảnh báo, xin vui lòng? – jrok

+0

là tệp này trong một tệp .h? – yngccc

+0

Bạn có một đối tượng của A bên trong lớp A. Làm thế nào để làm việc này? Điều này không trở thành đệ quy - ngay cả khi đối tượng là tĩnh. Mặc dù chỉ có một my_A & đệ quy sẽ không gây ra vấn đề, tôi vẫn có thể thực hiện 'A a; 'và sau đó a.mY_A.my_A.my_A.my_A v.v. – user93353

Trả lời

16

Dưới đây là một trường hợp đơn giản mà gây nên các cảnh báo tương tự:

class A { 
public: 
    // ... 
    A(); 
}; 

A my_A; // triggers said warning 


test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors] 
A my_A; // triggers said warning 
    ^~~~ 
1 warning generated. 

này là hoàn toàn hợp pháp và an toàn C++.

Tuy nhiên đối với mọi công cụ xây dựng toàn cầu không tầm thường bạn có, thời gian khởi chạy ứng dụng của bạn bị ảnh hưởng. Cảnh báo chỉ đơn giản là một cách để cho bạn biết về vấn đề hiệu suất tiềm năng này.

Bạn có thể vô hiệu hóa cảnh báo bằng -Wno-global-constructors. Hoặc bạn có thể thay đổi thành sơ đồ khởi tạo lười biếng như sau:

A& 
my_A() 
{ 
    static A a; 
    return a; 
} 

tránh vấn đề hoàn toàn (và ngăn chặn cảnh báo).

+10

Bạn có chắc chắn hiệu suất là vấn đề chính không? Tôi nghĩ rằng vấn đề lớn hơn có thể xuất hiện - vì thứ tự của hình cầu/thống kê khởi tạo không xác định trong C++, đối tượng toàn cầu không tầm thường có thể giới thiệu trong hàm khởi tạo của nó phụ thuộc vào một đối tượng toàn cầu khác, dẫn đến hành vi không xác định. – SomeWittyUsername

+0

okay cảm ơn. Tôi nghĩ rằng tôi đã bối rối bởi các từ ngữ * constructor toàn cầu *. Có lẽ một cái gì đó như * xây dựng lúc khởi động * sẽ thích hợp hơn. – Walter

+0

@icepack điểm tốt. Điều này thực sự có thể xảy ra trong mã của tôi, mặc dù tôi chưa bao giờ gặp phải sự cố ... – Walter

3

Giải pháp từ @Howard Hinnant tránh các nhà xây dựng toàn cầu, nhưng nó vẫn thoát khỏi thời gian tồn tại. Nó có thể được tìm thấy với tùy chọn -Wexit-time-destructors

giải pháp Vì vậy, lý tưởng có thể dựa trên CR_DEFINE_STATIC_LOCAL từ http://src.chromium.org/svn/trunk/src/base/basictypes.h

A& my_A() 
{ 
    static A &a = *new A; 
    return a; 
} 
+2

Mã này sẽ tạo cảnh báo từ các công cụ rò rỉ bộ nhớ. –

+1

tất nhiên! destructor sẽ không được gọi cho mã này. – Speakus

+0

@DavidFaure Không thể tránh rò rỉ bộ nhớ bằng cách giữ một 'static unique_ptr ' (thay vì 'static A &') bên trong 'A :: my_A()'? – Walter