Cho một biến thành viên tĩnh mà được khởi tạo từ một biến thành viên tĩnh của khác lớp, phi nghĩa đen struct ii
đôi khi được mặc định khởi tạo 0
hay để 333
. Điều này phụ thuộc vào trình biên dịch hoặc thứ tự liên kết. Mã giả để chứng minh:C++: tĩnh trên tĩnh biến thành viên khởi tạo phụ thuộc với int vs struct
class StaticClass: // file 'ONE.cpp/.hpp'
static int i = 2
static struct ii { int a = 333 }
class ABC: // file 'abc.cpp'
static int abc_i = StaticClass::i // always 2
static struct abc_ii = StaticClass::ii // sometimes 0, sometimes 333
Calling g++ -std=c++11 abc.cpp ONE.cpp && ./a.out
kết quả trong i = 2/ii = 0
(gcc 4.8.1, cùng với kêu vang ++ 3.7; -Wall -Wextra
không bao giờ phàn nàn).
Nhưng gọi g++ -std=c++11 ONE.cpp abc.cpp && ./a.out
kết quả bằng i = 2/ii = 333
!
Các tương tự xảy ra với ONE.o abc.o
vs abc.o ONE.o
và cũng có khi concatenating các tập tin một cách này hay cách khác:
cat ONE.cpp abc.cpp > X.cpp && g++ X.cpp && ./a.out
vs cat abc.cpp ONE.cpp > Y.cpp && g++ Y.cpp && ./a.out
Loại bỏ bao gồm và di chuyển mã xung quanh trong file duy nhất, khởi tạo mặc định để 0 xảy ra khi đơn hàng này xuất hiện:
const OneI ABC::def_ii = StaticClass::ii; const OneI StaticClass::ii = OneI{333};
và một đến 333 với trật tự này:
const OneI StaticClass::ii = OneI{333}; const OneI ABC::def_ii = StaticClass::ii;
Tại sao điều này thậm chí còn xảy ra với hai đơn vị biên soạn riêng biệt? Điều này có thể tránh được bằng cách nào đó bằng cách thực thi thứ tự sau này không? Đang sử dụng con trỏ tĩnh trong ABC
đến StaticClass::ii
an toàn (tôi không muốn, mặc dù)?
Full C++:
/* File: abc.cpp */
#include <iostream>
#include "ONE.hpp"
struct ABC {
ABC();
static const int def_i;
static const OneI def_ii;
void arg_i(const int &x) { std::cout << "i = " << x << " ";};
void arg_ii(const OneI &x) { std::cout << "/ ii = " << x.a << " ";};
};
ABC::ABC() {
arg_i(def_i);
arg_ii(def_ii);
}
const int ABC::def_i = StaticClass::i;
const OneI ABC::def_ii = StaticClass::ii;
int main() {
ABC a;
std::cout << '\n';
}
/* End: abc.cpp */
/* File: ONE.cpp */
#include <iostream>
#include "ONE.hpp"
const int StaticClass::i = 2;
const OneI StaticClass::ii = OneI{333};
/* End: ONE.cpp */
/* File: ONE.hpp */
#include <iostream>
#ifndef One
#define One
struct OneI {
OneI(int a_) : a(a_) { }
int a;
};
struct StaticClass {
const static int i;
const static OneI ii;
};
#endif // One header guard
/* End: ONE.hpp */
Bạn có thể muốn xây dựng trên các giai đoạn khởi tạo tĩnh và động và cách thiết lập thứ tự khởi tạo động bắt buộc. Nếu không câu trả lời của bạn ít hơn một nửa câu chuyện. –
@MaximEgorushkin Tôi đã thêm công cụ về khởi tạo tĩnh và động. Mặc dù nó giúp hiểu tại sao giá trị của 'StaticClass :: ii' chưa được khởi tạo phải bằng 0, tôi không đồng ý về ý nghĩa của nó đối với câu hỏi. – user2079303
Thứ tự a) không khởi tạo, b) khởi tạo tĩnh, c) khởi tạo động? Và vì 'const int StaticClass :: i = 2' là b),' const int ABC :: def_i = StaticClass :: i' là gì? Năng động, tôi sẽ đoán. – toting