2011-08-18 43 views
21

Với tiêu chuẩn C++ 11 mới, khi nào tôi nên sử dụng từ khóa inline trên từ khóa constexpr? Liệu từ khóa constexpr có cung cấp bất kỳ tối ưu hóa bổ sung nào qua số inline hay không chỉ đơn thuần khẳng định rằng mọi thứ phải được tính toán tại thời gian biên dịch?nội tuyến so với constexpr?

Tại sao constexpr hoạt động trên GCC trong một số trường hợp cuộc gọi không liên tục, chẳng hạn như gọi foo(x) trên biến số không constexpr? Đây có phải là một lỗi trong GCC hay nó thực sự là một phần của tiêu chuẩn?

Trả lời

26

Xác nhận rằng điều gì đó có thể được tính tại thời điểm biên dịch một loại tối ưu hóa khá mạnh.

Nội tuyến chỉ loại bỏ một cuộc gọi chức năng, bằng cách sao chép/dán nội dung chức năng vào trang cuộc gọi. Cơ thể chức năng vẫn phải được thực thi, bạn chỉ cần lưu phí trên của một cuộc gọi hàm.

Nhưng nếu bạn thực hiện cùng một mã được đánh giá tại thời điểm biên dịch, nó là miễn phí khi chạy.

Nhưng không phải inline cũng không constexprchủ yếu là về tối ưu hóa. Mục đích chính của inline là ngăn chặn quy tắc một định nghĩa, để các hàm có thể được xác định trong tiêu đề (có ích cho mẫu và tình cờ, cũng giúp tối ưu hóa nội tuyến dễ dàng hơn)

constexpr rất hữu ích trong lập trình meta, và tình cờ, nó có thể giúp trình biên dịch tối ưu hóa tốt hơn mã, bằng cách di chuyển nhiều tính toán hơn để biên dịch-thời gian.

+5

Theo [câu hỏi này] (http://stackoverflow.com/q/7065200/636019), khi các hàm 'constexpr' không được sử dụng trong ngữ cảnh yêu cầu biểu thức không đổi, trình biên dịch không bắt buộc phải tính biểu thức tại thời gian biên dịch. – ildjarn

+0

nhưng nó vẫn xác định rằng tính toán * có thể * được thực hiện tại thời gian biên dịch. Vì vậy, với 'inline', nó không thực sự là về tối ưu hóa, nhưng nó có thể cung cấp thêm thông tin mà trình biên dịch có thể sử dụng để tối ưu hóa. – jalf

+0

Đúng vậy, tôi chỉ đang sử dụng từ "phải" thôi. : -] – ildjarn

1

Để quote wikipedia:

C++ 0x sẽ giới thiệu các constexpr từ khóa, cho phép người dùng để đảm bảo rằng một hàm hoặc đối tượng constructor là một thời gian biên dịch liên tục.

Đánh dấu chức năng nội dòng nếu chúng siêu ngắn. Đánh dấu các hàm là constexpr nếu các kết quả được yêu cầu tại thời gian biên dịch. (Thông số mẫu hoặc kích thước mảng). Tôi tin rằng một chức năng có thể là cả hai nếu cần thiết.

Chức năng biểu thức liên tục hoặc hàm tạo có thể được gọi với thông số không tham số constexpr. Cũng giống như một số nguyên constexpr có thể là được gán cho một biến không constexpr, do đó, quá có thể một hàm constexpr được gọi với tham số không constexpr và kết quả được lưu trữ trong biến không phải constexpr. Từ khóa chỉ cho phép khả năng của thời gian biên dịch khi tất cả các thành viên của biểu thức là constexpr.

Vì vậy, GCC không chính xác trong trường hợp này.

-2

Trong khi inline nói với trình biên dịch "Chức năng này được sử dụng ở đâu đó trong đơn vị dịch này và không công khai đối với các tệp đối tượng khác", có khả năng trình biên dịch chèn phần thân của hàm vào người gọi. constexpr chức năng nói với trình biên dịch "Chức năng này không có tác dụng phụ và không phụ thuộc vào điều kiện tiên quyết khác với tham số itsself."

constexpr biến chỉ nói" Biến này không thay đổi và dữ liệu của nó có thể được bao gồm trong mã ". Tuy nhiên, nó tạo sự khác biệt nếu bạn xác định biến constexpr trong hàm tĩnh hoặc không tĩnh, ví dụ: nếu constexpr mảng là không tĩnh, gcc chỉ cần di chuyển dữ liệu với mã hóa cứng mov -instructions vào stack, trong khi static constexpr chỉ lưu trữ các dữ liệu trong .text -section.

Lambda biểu thức mà không chụp được gán cho một biến có thể được constexpr khác hơn so với chụp, bởi vì không có chúng không cần bộ nhớ để lưu lại và chúng hoạt động giống như một lớp rỗng với quá tải operator() (nhưng chúng thậm chí có thể được đưa vào hàm p đồng bằng) ointers với một đơn giản unary cộng: +[]{}).

+0

'inline' không ngụ ý liên kết nội bộ như bạn có vẻ đang nói trong đoạn đầu tiên của bạn –

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