2013-04-07 16 views

Trả lời

12

Bạn có thể ngừng sử dụng inline làm kỹ thuật tối ưu hóa.

inline về cơ bản chỉ hữu ích khi bạn muốn ODR (One Definition Rule) không áp dụng. Nói tóm lại, bạn có thể đánh dấu chức năng như inline và cung cấp định nghĩa của họ trực tiếp trong một tập tin tiêu đề, sau đó được nhập khẩu bởi nhiều đơn vị dịch thuật, mà không có mối liên kết phàn nàn về điều này:

foo.hpp

inline int foo() { return 42; } 

Foo.cpp

#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline, 
        //  because its definition is imported also in main.cpp 
void bar() 
{ 
    int x = foo(); 
} 

main.cpp

#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline, 
        //  because its definition is imported also in foo.cpp 
int main() 
{ 
    std::cout << foo(); 
} 

Sự hiện diện của từ khóa inline (trong đó, một lần nữa, không đảm bảo rằng trình biên dịch sẽ thực hiện nội tuyến) đảm bảo rằng trình liên kết sẽ hợp nhất các định nghĩa đó.

Dĩ nhiên, để cho hoạt động hợp nhất này có ý nghĩa, tất cả các định nghĩa của một hàm đánh dấu là inline mà kết thúc là một phần của các đơn vị dịch khác nhau phải giống hệt. Nếu đây không phải là trường hợp, chương trình của bạn có Hành vi không xác định và không cần chẩn đoán - điều đó có nghĩa là trình biên dịch/trình liên kết của bạn không bắt buộc phải phát hiện sự không nhất quán này và cho bạn biết có điều gì đó không ổn!

mỗi khoản 3.2/4 của Tiêu chuẩn C++ 11, trên thực tế:

Mỗi chương trình sẽ chứa chính xác một định nghĩa của tất cả các chức năng phi inline hoặc biến đó là ODR-sử dụng ở chỗ chương trình; không cần chẩn đoán. Định nghĩa có thể xuất hiện rõ ràng trong chương trình, có thể tìm thấy trong thư viện chuẩn hoặc thư viện do người dùng xác định, hoặc (khi thích hợp) được định nghĩa ngầm định (xem 12.1, 12.4 và 12.8). Một hàm nội tuyến sẽ được định nghĩa trong mọi đơn vị dịch mà nó không được sử dụng.

Chú ý, bạn có thể có chức năng tương tự được đánh dấu là inline và theo nghĩa đen được xác định hai lần trong các đơn vị dịch khác nhau, và đó là tốt miễn là những định nghĩa là giống hệt nhau:

Foo.cpp

inline int foo() // Has the same body in main.cpp, no problem! 
{ 
    return 42; 
} 

chính.cpp

inline int foo() // Has the same body in foo.cpp, no problem! 
{ 
    return 42; 
} 

int main() 
{ 
    std::cout << foo(); 
} 

Tuy nhiên, nếu hai định nghĩa khác nhau, bạn sẽ bơm UB trong mã của bạn, như trong ví dụ sau:

Foo.cpp

inline int foo() 
{ 
    return 42; // <== WATCH OUT! Different body in main.cpp 
} 

chính. cpp

inline int foo() 
{ 
    return -42; // <== WATCH OUT! Different body in foo.cpp 
} 

int main() 
{ 
    std::cout << foo(); 
} 

Đây là lý do tại sao bạn thường đánh dấu các hàm là inline khi bạn cung cấp định nghĩa của chúng trực tiếp trong tệp tiêu đề thường là #include d.

Cũng lưu ý rằng, các hàm thành viên của lớp có định nghĩa được gạch chân trực tiếp trong định nghĩa lớp được tự động đánh dấu là inline.

+0

Và, ngay cả khi bạn không bao giờ sử dụng 'inline', bạn vẫn có thể sử dụng nó một cách ngầm định:' struct Foo {int x; Foo(): x (0) {}}; 'trong một tệp .cpp và' struct Foo {double d; Foo(): d (0) {}}; 'trong một tệp .cpp khác, và bạn vừa tạo ra hai hàm tạo' inline' được gọi là 'Foo :: Foo' ... – Yakk

+1

@Yakk: Sau đó, chương trình của bạn có hành vi không xác định, trừ khi cả hai 'Foo' được khai báo trong một không gian tên ẩn danh. –

+0

@MatthieuM. Đúng, và tôi đã thấy điều đó xảy ra trong mã sản xuất. Về cơ bản, tôi nói rằng ngay cả khi bạn không sử dụng 'inline', bạn có thể bị cắn bởi nó, vì vậy bạn cần phải hiểu những gì' inline' thực sự là ngay cả khi bạn không sử dụng nó. – Yakk

5

Phụ thuộc vào mục đích sử dụng inline.

Phổ biến (mis) quan niệm:
inline chỉ là một gợi ý mà một trình biên dịch có thể hoặc không thể tuân thủ để. Một trình biên dịch tốt sẽ anyways làm những gì cần phải được thực hiện.

Trong khi, sự thật:

inline thường chỉ đến việc thực hiện mà thay inline của cơ quan chức năng tại thời điểm gọi là được ưa thích cơ chế chức năng cuộc gọi bình thường. Việc triển khai không bắt buộc để thực hiện thay thế nội tuyến này tại điểm gọi; tuy nhiên, ngay cả khi việc thay thế inline này bị bỏ qua, các quy tắc khác (đặc biệt là w.r.t One Definition Rule) cho inline được theo sau.

Vì vậy, nếu mục đích sử dụng của bạn là tối ưu hóa câu trả lời là:

YES, Bạn có thể ngừng sử dụng inline. Hầu hết các trình biên dịch hiện đại sẽ làm điều đó cho bạn khá độc đáo.

Nhưng nếu mục đích sử dụng của bạn của inline là cho phép bạn để có được quá khứ một quy tắc định nghĩa và xác định một cơ quan chức năng trong một tập tin tiêu đề mà không vi phạm ODR sau đó trả lời là:

NO , Bạn cần đánh dấu rõ ràng các hàm là inline để có thể bỏ qua ODR.

Lưu ý: Các hàm thành viên được định nghĩa trong cơ thể lớp đang ngầm inline, nhưng cùng không áp dụng cho các chức năng miễn phí.

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