2012-04-11 33 views
25

Sự khác biệt giữa việc sử dụng từ khóa nội tuyến trước một hàm và chỉ khai báo toàn bộ hàm trong tiêu đề là gì?Từ khóa nội tuyến và định nghĩa tiêu đề

như vậy ...

int whatever() { return 4; } 

vs

.h:

inline int whatever(); 

cpp:

inline int myClass::whatever() 
{ 
    return 4; 
} 

cho rằng vấn đề, những gì hiện làm điều này:

inline int whatever() { return 4; } 

Trả lời

10

mà khônginline, bạn sẽ có khả năng kết thúc với nhiều khẩu hiệu, nếu hàm được khai báo ở namespace hay toàn cầu phạm vi (kết quả trong mối liên kết lỗi). Tuy nhiên, hầu hết các trình biên dịch ngầm khai báo phương thức là nội tuyến (-fno-default-inline sẽ vô hiệu hóa mặc định đó trên GCC).

nếu bạn khai báo hàm là nội dòng, trình biên dịch có thể mong đợi để xem định nghĩa của nó trong bản dịch. do đó, bạn nên bảo lưu nó cho những lần định nghĩa được hiển thị.

ở cấp cao hơn: định nghĩa trong khai báo lớp thường hiển thị với nhiều bản dịch hơn. điều này có thể dẫn đến tối ưu hóa tốt hơn và có thể dẫn đến tăng thời gian biên dịch.

trừ khi tối ưu hóa tay và biên dịch nhanh đều quan trọng, việc sử dụng từ khóa trong khai báo lớp là điều không bình thường trong những ngày này.

2

Câu hỏi này giải thích rất nhiều về chức năng inline What does __inline__ mean ? (mặc dù nó đã được về inline từ khóa.)

Về cơ bản, nó không có gì để làm với tiêu đề. Khai báo toàn bộ chức năng trong header chỉ thay đổi tập tin nguồn có nguồn gốc của hàm này. Từ khóa inline sửa đổi nơi kết quả là hàm biên dịch sẽ được đặt ở vị trí riêng của nó, để mọi cuộc gọi đến đó, hoặc thay cho mọi cuộc gọi (tốt hơn cho hiệu suất). Tuy nhiên, các trình biên dịch đôi khi chọn các hàm hoặc phương thức nào để tạo nội tuyến cho chính chúng và từ khóa chỉ đơn giản là các đề xuất cho trình biên dịch. Ngay cả các hàm không được chỉ định nội dòng có thể được trình biên dịch chọn để trở thành nội tuyến, nếu điều đó cho hiệu năng tốt hơn.

1

Nếu bạn đang liên kết nhiều đối tượng thành một tệp thực thi, thường chỉ có một đối tượng chứa định nghĩa hàm. Đối với int whatever() { return 4; } - bất kỳ đơn vị dịch nào được sử dụng để tạo một đối tượng sẽ chứa định nghĩa (tức là mã thực thi) cho hàm whatever. Người liên kết sẽ không biết người nào hướng người gọi đến. Nếu inline được cung cấp, thì mã thực thi có thể hoặc không thể được gạch chân tại các trang gọi, nhưng nếu không phải là trình liên kết được cho phép giả định rằng tất cả các định nghĩa đều giống nhau, và chọn một tùy ý cho người gọi trực tiếp. Nếu bằng cách nào đó các định nghĩa không giống nhau, thì nó được coi là lỗi của bạn và bạn nhận được hành vi không xác định.Để sử dụng inline, định nghĩa phải được biết khi biên dịch cuộc gọi, vì vậy ý ​​tưởng của bạn về việc đặt một khai báo nội tuyến trong tiêu đề và định nghĩa nội tuyến trong tệp .cpp sẽ chỉ hoạt động nếu tất cả người gọi xảy ra sau đó trong cùng một tệp .cpp tập tin - nói chung nó bị hỏng, và bạn mong đợi định nghĩa của hàm nội tuyến (danh nghĩa) xuất hiện trong tiêu đề khai báo nó (hoặc để có một định nghĩa duy nhất mà không cần khai báo trước).

28

Có một số khía cạnh:

Ngôn ngữ

  • Khi một hàm được đánh dấu với từ khóa inline, sau đó định nghĩa của nó nên có sẵn trong TU hoặc chương trình là vô hình thành.
  • Bất kỳ hàm nào được xác định ngay trong định nghĩa lớp đều được đánh dấu rõ ràng inline.
  • Một chức năng được đánh dấu inline (ngầm hoặc rõ ràng) có thể được xác định trong một số TU (tôn trọng ODR), trong khi đó không phải là trường hợp cho các chức năng thông thường.
  • Chức năng mẫu (không hoàn toàn chuyên biệt) được xử lý giống như inline.

Compiler hành vi

  • Một chức năng đánh dấu inline sẽ được phát ra như một biểu tượng yếu trong mỗi tập tin đối tượng, nơi nó là cần thiết, điều này có thể làm tăng kích thước của chúng (nhìn lên mẫu sưng lên).
  • Trong khi trình biên dịch thực sự nhấn mạnh cuộc gọi (ví dụ, sao chép/dán mã tại điểm sử dụng thay vì thực hiện cuộc gọi chức năng thông thường) hoàn toàn theo quyết định của trình biên dịch. Sự hiện diện của từ khóa có thể hoặc không ảnh hưởng đến quyết định nhưng tốt nhất là một gợi ý .

hành vi Linker

  • ký Yếu được sáp nhập với nhau để có một lần xuất hiện trong thư viện chính thức. Một mối liên kết tốt có thể kiểm tra rằng nhiều định nghĩa đồng ý nhưng điều này là không cần thiết.
+6

Bạn có ý nghĩa gì với "TU" và "ODR"? – WiSaGaN

+4

@WiSaGaN: TU = Đơn vị dịch: khoảng, tệp nguồn được xử lý trước. ODR = Một quy tắc định nghĩa: yêu cầu tất cả các định nghĩa của một hàm/lớp phải giống hệt nhau, ở cấp độ ký tự, qua các TU. –

+0

Ở cấp độ ký tự hoặc ở cấp mã thông báo? – fredoverflow

9

Mục đích của inline là cho phép hàm được xác định trong nhiều đơn vị dịch, cần thiết cho một số trình biên dịch để có thể nội tuyến ở bất cứ nơi nào được sử dụng. Nó nên được sử dụng bất cứ khi nào bạn định nghĩa một hàm trong một tệp tiêu đề, mặc dù bạn có thể bỏ qua nó khi xác định một khuôn mẫu hoặc một hàm bên trong một định nghĩa lớp.

Xác định tiêu đề trong tiêu đề mà không inline là một ý tưởng rất tồi tệ; nếu bạn bao gồm tiêu đề từ nhiều đơn vị dịch thì bạn sẽ phá vỡ Quy tắc Một Định nghĩa; mã của bạn có thể sẽ không liên kết và có thể biểu hiện hành vi không xác định nếu có.

Khai báo nó trong tiêu đề với inline nhưng xác định nó trong tệp nguồn cũng là một ý tưởng rất tồi tệ; định nghĩa phải có sẵn trong bất kỳ đơn vị dịch nào sử dụng nó, nhưng bằng cách xác định nó trong một tệp nguồn, nó chỉ có sẵn trong một đơn vị dịch. Nếu một tệp nguồn khác bao gồm tiêu đề và cố gắng gọi hàm, thì chương trình của bạn không hợp lệ.

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