2016-06-12 14 views
9

Hãy xem xét những điều sau đây, nơi chúng tôi đã hai tập tin scoped đối tượng trong đơn vị dịch khác nhau, đó là thiết lập thông thường cho không xác định-cư xử theo cách của sự thất bại để khởi tạo:Các tệp nguyên tử có phạm vi tệp có phải là sự thất bại của lệnh khởi tạo không?

a.hpp:

struct thing { 
public: 
    thing(int value); 
    ~thing(); 

    int value() const; 

    static int count(); 

private: 
    int _value; 
}; 

a.cpp:

#include "a.hpp" 

#include <atomic> 

namespace { 
    std::atomic<int> things; 
} 

thing::thing(int value) : _value(value) { 
    ++things; 
} 

thing::~thing() { 
    --things; 
} 

int thing::value() const { 
    return _value; 
} 

int thing::count() { 
    return things.load(); 
} 

b.cpp:

#include <iostream> 

#include "a.hpp" 

namespace { 
    thing static_thing(42); 
} 

void foo() { 
    std::cout << static_thing.value() << ' ' << thing::count() << '\n'; 
} 

là mã này tuân theo một trật tự thất bại khởi giữa các tập tin scoped nguyên tử things trong a.cpp và file scoped static_thing trong b.cpp? Nếu không, tai sao không? Đặc biệt, những gì là đặc biệt về std :: nguyên tử mà loại bỏ những gì nếu không sẽ là một sự thất bại trật tự init rõ ràng? Có một khái niệm cụ thể có thể được đặt tên để thực thi điều này với một khẳng định tĩnh không? Một cái gì đó như:

static_assert(std::is_trivial<decltype(things)>::value, "file static counter is not trivial"); 

Nếu không std::is_trivial, có khái niệm nào khác và đặc điểm kiểu liên kết mô hình tốt hơn không?

Ngược lại, có một thất bại không khởi tạo không? Cùng một câu hỏi về nếu như vậy, tại sao, hoặc tại sao không.

+0

nghiên cứu ngắn gọn của tôi trong vấn đề này cho thấy rằng việc đưa ra sự đảm bảo rằng 'std :: nguyên tử ' phải được chuyên môn, và Atomics chuyên ngành có tính chất nhất định, 'std :: nguyên tử 'sẽ giống như một POD, để khởi tạo thứ tự, ví dụ không có thất bại. Tuy nhiên, trường hợp này cũng có thể được giải quyết giống như hầu hết các trường hợp khác bắt đầu với dấu phẩy: nhưng khai báo các đối tượng tĩnh trong phạm vi tĩnh chức năng, và lợi dụng thực tế là các đối tượng có phạm vi tĩnh chức năng phải là init-ed trước lần nhập đầu tiên chức năng. –

+2

Thứ tự xây dựng các đối tượng tĩnh trong các bản dịch khác nhau vẫn chưa được chỉ định. Sử dụng 'std :: atomic' không thay đổi điều đó. Tại sao bạn mong đợi nó? Các trình biên dịch đặc biệt có thể khởi tạo các nguyên tử đầu tiên, nhưng điều đó không bắt buộc. – Peter

+0

@Peter vì std :: nguyên tử có một hàm tạo constexpr và đang được khởi tạo với hằng số và có một hàm hủy nhỏ. Điều này cho thấy rằng đối tượng có hiệu quả bất tử. Vì init tĩnh diễn ra trước bất kỳ init động nào, và vì không có gì phải làm để tiêu diệt nó, nó cơ bản là bất tử. Tôi không thấy làm thế nào có thể có một fiasco thứ tự khởi tạo w.r.t. bất cứ điều gì với khởi tạo động. – acm

Trả lời

1

Sự hiểu biết của tôi về C++ "fiasco thứ tự khởi tạo" là nó chỉ áp dụng khi các nhà thầu cần được gọi khi chạy. Nếu mã có thể phân giải thành phần khởi tạo của vị trí bộ nhớ thành giá trị cố định, thì giá trị đó được đặt trong phần liên kết "dữ liệu được khởi tạo" (.data) như mọi POD được khởi tạo trước khác (Dữ liệu đồng bằng Ol) và ở đó không phải là thất bại.

Tôi muốn đề xuất rằng một số atomic đáp ứng tiêu chí đó.

2

std::atomic<> là loại bố cục chuẩn với các hàm tạo mặc định tầm thường và các trình phá hủy tầm thường. Do đó, nó được khởi tạo tại khởi tạo tĩnh pha, trước khi khởi động động động khi các hàm tạo của các đối tượng chung được gọi.

Nói cách khác, không có sự thất bại thứ tự khởi tạo xảy ra ở đây.

Vì bạn không khởi tạo rõ ràng vùng tên được đặt std::atomic<int>, nó sẽ không được khởi tạo.

§ 3.6.2 Khởi tạo các biến phi địa phương

biến với thời gian tĩnh lưu trữ (3.7.1) hoặc thời gian lưu trữ chủ đề (3.7.2) sẽ được zero-khởi (8,5) trước khi bất kỳ khác khởi tạo diễn ra.

Cùng nhau, không khởi tạo và khởi tạo liên tục được gọi là khởi tạo tĩnh; tất cả các khởi tạo khác là khởi tạo động. Việc khởi tạo tĩnh sẽ được thực hiện trước khi bất kỳ khởi tạo động nào diễn ra.

+0

Đây là lỗi trình biên dịch modulo đúng (Xem [this one] (https://developercommunity.visualstudio.com/content/problem/76198/vs-2017-compiler- create-broken-debug-build-using.html) có ảnh hưởng đến VS 2017 15.3) – Arnaud

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