2010-11-16 37 views
15

Tôi không thể hiểu được hành vi sau: một tiêu đề có một số loại cơ bản và một tiêu đề khác mà tôi sử dụng các loại này trong một số hàm. Sau đó, tôi bắt đầu xây dựng các lớp dựa trên các kiểu và hàm đã định nghĩa của mình. Trong tiêu đề chức năng nếu tôi để lại chữ ký sau:Liên kết hàm nội tuyến

void whateverFunction(parameters) 

Mối liên kết chỉ ra rằng có nhiều định nghĩa của hàm bất kỳ. Bây giờ, nếu thay đổi thành:

inline void whateverFunction(parameters) 

sự cố liên kết đã biến mất và tất cả biên dịch và liên kết đều tốt. Những gì tôi biết liên quan đến nội tuyến là nó thay thế tất cả các cuộc gọi chức năng với mã của nó khác hơn là nó khá tối, vì vậy câu hỏi của tôi là:

Trình liên kết xử lý các hàm nội tuyến trong C++ như thế nào?

+1

Xem ["mục đích là gì?"] (Http://stackoverflow.com/questions/3647053/what-is-are-the-purposes-of-inline) để biết chi tiết , đặc biệt là một phần trong * Quy tắc một định nghĩa *. –

Trả lời

20

Khi hàm trong tiêu đề không phải là nội tuyến, thì nhiều định nghĩa của hàm này (ví dụ: trong nhiều đơn vị dịch) là vi phạm các quy tắc ODR.

Chức năng nội tuyến theo mặc định có liên kết bên ngoài. Do đó, như một hệ quả của quy tắc ODR (đưa ra dưới đây), nhiều định nghĩa như vậy (ví dụ trong nhiều đơn vị dịch) là Okay:

$ 3,2/5- "Có thể có nhiều hơn một nghĩa của một kiểu lớp (khoản 9), kiểu enumeration (7.2), inline chức năng với mối liên hệ bên ngoài (7.1.2), lớp mẫu (khoản 14), chức năng không tĩnh mẫu (14.5.6), tĩnh thành viên dữ liệu mẫu lớp học (14.5.1.3), chức năng thành viên của lớp học mẫu (14.5.1.1) hoặc mẫu chuyên môn hóa một số thông số mẫu không được chỉ định (14.7, 14.5.5) trong một chương trình với điều kiện mỗi định nghĩa xuất hiện trong đơn vị dịch khác nhau và cung cấp các định nghĩa đáp ứng các yêu cầu sau. Cho một thực thể như vậy có tên D được xác định trong nhiều đơn vị dịch , sau đó

- mỗi định nghĩa của D phải bao gồm của cùng một chuỗi mã thông báo; và [...]

Cách trình liên kết xử lý các hàm nội tuyến là chi tiết mức độ triển khai khá nhiều. Đủ để biết rằng việc triển khai chấp nhận các định nghĩa mulitple như vậy trong các giới hạn của các quy tắc ODR

Lưu ý rằng nếu hàm khai báo trong tiêu đề được thay đổi thành 'static inline ....', thì hàm inline rõ ràng có liên kết bên trong và mỗi đơn vị dịch có bản sao riêng của hàm nội tuyến tĩnh.

+0

* Chức năng nội tuyến theo mặc định có liên kết bên ngoài. *: Tôi thấy tuyên bố này gây hiểu nhầm. Mã nội tuyến không được liên kết chút nào, ít nhất không phải dưới tên hàm. Xem [Câu trả lời của Marcelo] (http://stackoverflow.com/a/4193657/772981). – Jarekczek

+3

Trên các trình biên dịch hiện đại, người ta có thể thấy 'inline' như một từ khóa để cho phép nhiều định nghĩa thay vì tối ưu hóa gợi ý. Trình biên dịch có thể quyết định không inline một hàm inline, và trình liên kết có thể chọn bất kỳ một trong các đơn vị biên dịch. Lập trình viên phải đảm bảo rằng một hàm nội tuyến trên các đơn vị biên dịch là giống hệt nhau. Nếu không hành vi không xác định phát sinh. – jdh8

9

Trình liên kết có thể không thấy chức năng nội tuyến. Chúng thường được biên dịch thẳng vào mã gọi chúng (ví dụ: mã được sử dụng thay cho cuộc gọi hàm).

Nếu trình biên dịch chọn không inline chức năng (vì nó chỉ là một gợi ý), tôi không chắc chắn, nhưng tôi nghĩ trình biên dịch phát ra nó như là một hàm không inline bình thường và bằng cách nào đó chú thích nó chọn bản sao đầu tiên mà nó nhìn thấy và bỏ qua những người khác.

0

Nội tuyến chỉ che dấu sự cố. Có nhiều định nghĩa chỉ ra một vấn đề ở đâu đó.

Juste cẩn thận về cách bạn sử dụng tiêu đề của mình. Đừng quên: - < < #ifndef HEADER_NAME/#define HEADER_NAME/#endif >> để tránh nhiều sự bao gồm. - Không sử dụng bao gồm gián tiếp: nếu bạn sử dụng một loại trong một tệp, hãy thêm tiêu đề tương ứng, ngay cả khi một tiêu đề khác trong cùng một tệp bao gồm nó.

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