2011-07-05 39 views
6

Im nghiên cứu các hàm nội tuyến trong C++ và đã đến một phần liên quan đến những hạn chế trong việc sử dụng nó. Nó nói:Lần khi không thể sử dụng chức năng nội tuyến

Trình biên dịch cũng không thể thực hiện nội tuyến nếu địa chỉ của chức năng được thực hiện ngầm hoặc một cách rõ ràng.

Ai đó có thể giải thích cho tôi, có lẽ với ví dụ về một số loại, điều này có nghĩa là gì?

+3

Oh Tôi ghét hệ thống downvotes câu hỏi miễn phí mới này. Cái quái gì sai với câu hỏi này, mọi người? –

+0

Trong tò mò, cuốn sách nào đang đưa ra tuyên bố đó? –

+1

+1 để truy cập vô danh drive-by downvoter –

Trả lời

5

Có hai quyết định có phần riêng biệt trình biên dịch làm liên quan đến chức năng nội tuyến:

  • liệu một chức năng cuộc gọi cụ thể được inlined;
  • liệu phiên bản không nội tuyến của hàm có tồn tại hay không.

Việc đầu tiên được quyết định bởi trình biên dịch theo từng trường hợp, nếu nội tuyến có thể thực hiện tại thời điểm đó. Sẽ không thể thực hiện được nếu hàm này là ảo, hoặc được gọi thông qua một con trỏ hàm, và nó không thể xác định tại thời gian biên dịch mà hàm sẽ được gọi. Nó sẽ không thể nếu định nghĩa không có sẵn cho trình biên dịch, có lẽ bởi vì nó được định nghĩa trong một đơn vị dịch khác và trình biên dịch không làm "tối ưu toàn bộ chương trình". Quyết định có thể, hoặc có thể không, bị ảnh hưởng bởi liệu chức năng có được khai báo là inline hay không và các yếu tố khác như kích thước của nó và tần suất được gọi.

Tùy chọn thứ hai phụ thuộc vào việc liệu có phải phiên bản không phải nội tuyến hay không. Nó sẽ được yêu cầu nếu bất kỳ cuộc gọi đến nó không phải là inlined. Nó cũng sẽ (theo báo giá của bạn) được yêu cầu nếu bất cứ điều gì cần địa chỉ của hàm, vì nó phải có một địa chỉ. Điều này có thể xảy ra trực tiếp (ví dụ bằng cách gán địa chỉ cho một con trỏ hàm), hoặc gián tiếp (ví dụ, các hàm ảo sẽ cần địa chỉ của chúng được lưu trữ ở đâu đó để tra cứu theo thời gian chạy theo kiểu động của đối tượng).

Sự tồn tại của phiên bản không nội tuyến sẽ không ngăn cản bất kỳ cuộc gọi cụ thể nào đến chức năng này, mặc dù có thể ảnh hưởng đến quyết định của trình biên dịch, đặc biệt nếu nó được định cấu hình để tối ưu hóa kích thước mã.

Để tóm tắt, báo giá của bạn đơn giản và không hoàn toàn chính xác; trình biên dịch vẫn có thể "thực hiện nội tuyến" nếu địa chỉ được thực hiện, nó chỉ không thể bỏ qua phiên bản không nội tuyến.

+0

Cảm ơn, ví dụ của bạn về gán địa chỉ với một con trỏ hàm thực sự giúp hiểu ý nghĩa của câu lệnh này. –

4

Nó chỉ là sai: khả năng inline một cuộc gọi chức năng không bị ảnh hưởng bởi tính toán 2 + 2 hoặc bằng cách lấy địa chỉ của hàm ở đâu đó.

Bạn đang đọc sách hoặc bài viết nào?

Mặt khác, nếu lấy địa chỉ thì thực tế là không thể loại bỏ chức năng mã máy riêng biệt.

Cheers & h.,

+0

http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter09_009.html –

+0

Ồ, "Suy nghĩ trong C++" của Bruce Eckel. Vâng, khá nhiều lỗi trong cuốn sách đó đã nổi lên qua nhiều năm. Nhưng theo như tôi biết Lý Tiểu Long chưa bao giờ sửa chữa bất cứ điều gì. Vì vậy, hãy cẩn thận. Ông viết một số công cụ tốt cho người mới, nhưng ông cũng viết những thứ vô nghĩa và không chính xác. Như anh đã làm ở đây. –

+0

Chỉ khi bạn đề cập đến những sai lầm, trong một câu hỏi trong cuốn sách, nó yêu cầu bạn tạo một lớp trong một tệp tiêu đề có chứa một hàm nội tuyến được gọi là in. Tuy nhiên, trong giải pháp sách, nó chỉ có khai báo print() trong phần đầu và định nghĩa của nó trong một tệp riêng biệt. Tôi có quyền nói rằng đây cũng là một sai lầm và nếu tôi muốn một hàm nội tuyến trong một tệp tiêu đề, nó phải bao gồm cả định nghĩa và khai báo để nó là một hàm nội tuyến? –

6

Bạn có thể đánh dấu bất kỳ chức năng như inline. Ngay cả một chức năng ảo, ngay cả một chức năng đệ quy, thậm chí là một chức năng dài veeery veery, ngay cả khi địa chỉ của nó được thực hiện. Sự khác biệt chính giữa một hàm inline và non-inline là định nghĩa của hàm trước phải xuất hiện trong mọi đơn vị dịch (còn gọi là tệp nguồn) mà nó được sử dụng (đó là lý do tại sao hàm inline thường được định nghĩa trong tệp .h), trong khi sau này phải được xác định chỉ một lần. Bạn có thể sử dụng hàm inline theo mọi cách mà bạn có thể sử dụng một hàm không nội tuyến.

Phần nội tuyến thực tế là tùy thuộc vào trình biên dịch. Nó có thể bỏ qua yêu cầu của bạn, nếu, ví dụ, chức năng của bạn là đệ quy hoặc quá dài. Mặt khác, trình biên dịch có thể chọn inline một hàm mà bạn chưa thực sự đánh dấu là inline.

+1

trong các phiên bản mới hơn của GCC, có một tùy chọn để tối ưu hóa toàn bộ chương trình - mà AFAIK, sẽ đưa ra yêu cầu đặt bất kỳ mã nào bạn hy vọng được gạch chân trong tiêu đề, dự phòng ... – Nim

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