2011-04-01 26 views
14

Tôi đang bối rối bởi các mối liên kết lỗi khi sử dụng đoạn mã sau:"static const int" gây liên kết lỗi (undefined-reference)

// static_const.cpp -- complete code 
#include <vector> 

struct Elem { 
    static const int value = 0; 
}; 

int main(int argc, char *argv[]) { 
    std::vector<Elem> v(1); 
    std::vector<Elem>::iterator it; 

    it = v.begin(); 
    return it->value; 
} 

Tuy nhiên, điều này không thành công khi liên kết - bằng cách nào đó nó cần phải có một biểu tượng cho giá trị const tĩnh "."

$ g++ static_const.cpp 
/tmp/ccZTyfe7.o: In function `main': 
static_const.cpp:(.text+0x8e): undefined reference to `Elem::value' 
collect2: ld returned 1 exit status 

BTW, điều này biên dịch tốt với -O1 hoặc cao hơn; nhưng nó vẫn không thành công cho các trường hợp phức tạp hơn. Tôi đang sử dụng phiên bản gcc 4.4.4 20100726 (Red Hat 4.4.4-13).

Bất kỳ ý tưởng nào có thể sai với mã của tôi?

+1

có thể trùng lặp của [Biểu thức không xác định trước của hằng số tĩnh bên trong một cấu trúc/lớp] (http://stackoverflow.com/questions/4891067/weird-undefined-symbols-of-static-constants-inside-a-struct- lớp học) – karlphillip

+0

Cảm ơn bạn đã liên kết hữu ích! Nó cũng cho thấy một giải pháp thay thế, 'struct Elem {enum {value = 0}; } ', có vẻ khá hấp dẫn. – hrr

+0

có thể trùng lặp của [C++ - xác định các thành phần nguyên const tĩnh trong định nghĩa lớp] (http://stackoverflow.com/questions/3025997/c-defining-static-const-integer-members-in-class-definition) – ks1322

Trả lời

8

Nếu bạn muốn khởi tạo nó bên trong struct, bạn có thể làm điều đó quá:

struct Elem { 
    static const int value = 0; 
}; 

const int Elem::value; 
+0

Đây là mát mẻ! Nó hoạt động. Nó không có ý nghĩa để không khởi tạo nó trong cấu trúc (lớp) nếu bạn có thể (biết giá trị tại thời điểm đó) bởi vì nếu không tất cả các tối ưu hóa có thể sẽ bị mất. (tức là truyền 0 trực tiếp thay vì tải 0 từ một số địa chỉ bộ nhớ.) –

+0

Nếu điều này thực sự là const, có sự thay thế của "enum hack", xem: http://stackoverflow.com/questions/4891067/weird-undefined -symbols-of-static-constants-bên trong-a-struct-class Các vấn đề cũng được mô tả ở đó: trước khi C++ 11 enums không có "kiểu" phong nha như 'int', do đó std :: min, std :: make_pair v.v. sẽ không đoán đối số mẫu của chúng ... –

5

Hãy thử viết nó như

struct Elem { 
    static const int value; 
}; 

const int Elem::value = 0; 

etc 

.

+0

Điều này sẽ không hoạt động, khi giá trị là nhãn trong câu lệnh chuyển đổi. – Petr

+0

@Petr Xin lỗi, không chắc chắn những gì để cho bạn biết ở đó. Tôi đã không sử dụng C + + trong một vài năm, vì vậy tôi không biết nếu đó là đặc biệt để 'const tĩnh' hoặc những gì. – jonsca

+1

Tôi nên làm cho bản thân mình rõ ràng hơn. Tôi đã cố gắng chỉ ra cho bất cứ ai đọc bạn trả lời, rằng - mặc dù hoàn toàn chính xác - có những trường hợp khi điều này sẽ không hoạt động. Ví dụ: nếu bạn muốn sử dụng 'giá trị' làm nhãn trong chuyển đổi, chẳng hạn như' switch (x) {case value: break; } ' – Petr

2

static thành viên của lớp thường được định nghĩa bên ngoài lớp (được khai báo bên trong, được định nghĩa bên ngoài) trong một đơn vị biên dịch.

Tôi không nhớ cách tương tác với khởi tạo nội tuyến của const thành viên tích phân tĩnh.

+1

xem http://stackoverflow.com/questions/1312241/using-a-static-const-int-in-a-struct-class/1312267#1312267 –

+1

Không có quy tắc đặc biệt cho trường hợp tờ khai có initializer --- theo tiêu chuẩn, đối tượng được khai báo phải được định nghĩa ở đâu đó nếu nó có khả năng được sử dụng. Trong thực tế, hầu hết các trình biên dịch đều có lỗi về vấn đề này và sẽ chỉ tạo ra một lỗi cho một số sử dụng nhất định, không phải cho những người khác, nếu định nghĩa bị thiếu. (Việc sử dụng nào không bao giờ được chỉ định và thường thay đổi tùy thuộc vào mức tối ưu hóa.) –

1

Tại sao không chỉ thực hiện việc này?

return Elem::value; 

Nhưng câu trả lời là bạn chỉ định giá trị trong khai báo. Điều này được cho là hoạt động đối với các loại cơ bản như int và chỉ bắt buộc đối với các loại phức tạp (ví dụ: các lớp, chẳng hạn như nếu bạn có chuỗi thay vì int). Những gì tôi đã tìm thấy trong thực tế là đây là hit hoặc bỏ lỡ tùy thuộc vào phiên bản của trình biên dịch bạn đang sử dụng. Và, khi bạn phát hiện ra, mức độ tối ưu hóa nào.

+0

Tuy nhiên, điều đó không giải quyết được vấn đề khởi tạo. Ngoài ra, nhấn hoặc bỏ lỡ thường có nghĩa là hành vi không xác định. – jonsca

+4

Thats chỉ tránh câu hỏi mà anh ta hỏi. –

+0

Thực ra tôi đã trả lời nó. Tôi nói rằng những gì anh ấy đang làm nên hoạt động (tức là không có gì sai), nhưng trong thực tế không phải lúc nào cũng hiệu quả. Ông dường như đã tìm thấy một trong những trường hợp "không hoạt động". –

2

Cũng thấy this post: về cơ bản, vấn đề là trình biên dịch nào đó sẽ mở rộng mã của bạn để lấy địa chỉ của Elem :: value.

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