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.
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. –
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
@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