2011-09-28 37 views
9

Đã thử điều này trong GCC 4.6 và nó biên dịch và liên kết, nhưng đưa ra thông báo "lỗi bus" khi chạy trên MacOS. VS2010 thậm chí không biên dịch nó.Đây có phải là mã C++ 0x chính xác không?

Nhưng câu hỏi đặt ra là, liệu điều này có thực sự hoạt động ở chuẩn C++ 0x không?

#include <cstdio> 
int (*main)()=[]()->int{printf("HEY!\n");return 0;}; 

Có, điều bạn đang cố làm là định nghĩa "chính" làm hàm lambda.

+13

Tôi thích cách bạn đang cố gắng sử dụng các tính năng mới nhất, tuyệt vời nhất, nâng cao của C++ 11, nhưng vẫn nhấn mạnh vào việc sử dụng 'cstdio' và' printf' :-) – paxdiablo

+4

@paxdiablo: printf rocks !!! C++ không thành công tại các luồng I/O :) –

+1

Theo Stroustroup ... nếu C cho phép bạn bắn vào chân, C++ có thể thổi tất cả các chân của bạn ra! Đây là điều tôi gọi là ... tình trạng bạo dâm! :-)) –

Trả lời

14

Đây không phải là chương trình C++ hợp lệ, vì biểu tượng main không được định nghĩa là hàm, mà là một con trỏ để hoạt động. Đó là lý do tại sao bạn nhận được lỗi phân đoạn - thời gian chạy là cố gắng thực hiện một con trỏ.

+0

+1: (Đã xóa nhận xét cẩu thả của tôi về câu hỏi gốc. Câu trả lời đó giải thích rõ hơn những gì đang xảy ra ở đây.) –

+0

Sau đó, tôi đoán đó thực sự là lỗi trong GCC mà nó chấp nhận mã này là chính xác? – hasvn

+0

@ hasvn, tôi không chắc chắn, nhưng tôi nghĩ đây là một trong những trường hợp mà không cần chẩn đoán theo tiêu chuẩn. Vì vậy, gcc có thể rõ ràng. – avakar

3

Không, điều này không chính xác.

Chính là một chức năng đặc biệt và có những yêu cầu nghiêm ngặt đối với nó (thậm chí nghiêm ngặt hơn chức năng thông thường), nhưng bạn cũng đang gây nhầm lẫn giữa hàm là gì và con trỏ trỏ đến hàm nào.

Vấn đề logic là có sự khác biệt giữa hàm và biến chứa con trỏ trỏ đến hàm (bạn muốn chính). Một hàm có địa chỉ cố định trong bộ nhớ, do đó, để gọi một hàm mà địa chỉ được gọi đơn giản. Một con trỏ đến một hàm điểm đến một địa chỉ trong bộ nhớ, do đó, để gọi hàm bạn cần trước tiên để đọc những gì con trỏ trỏ đến và sau đó gọi địa chỉ đó.

Một con trỏ tới hàm có mức độ khác nhau của tính không xác định từ một hàm.

Cú pháp giống nhau ... tức là nếu x là con trỏ đến hàm bạn có thể viết x(42), nhưng mã máy được tạo khác nếu x thay vào đó là hàm (trong trường hợp con trỏ, giá trị phải được tra cứu và địa chỉ cuộc gọi được xác định tại thời gian chạy, với một hàm địa chỉ được cố định - lên để di dời - và được xác định tại thời gian liên kết).

0

Để di chuyển giữa các trình biên dịch và triển khai thư viện chuẩn, printf() phải là tiêu chuẩn :: printf() khi #including <cstdio>. Và các nội dung khác về chính không hợp lệ().

+0

Không, nó không được chỉ định trong tiêu chuẩn về việc liệu 'cXXX' có đưa vào không gian tên chung hay không. Đó là _wise_ để sử dụng 'std ::' nhưng "phải" có lẽ là quá mức cần thiết. – paxdiablo

+0

OK, đây là trò đùa nửa chừng. Tôi sẽ chỉnh sửa câu trả lời cần lưu ý rằng nó cần thiết cho tính di động. (Những người trong chúng ta viết mã di động để kiếm sống chỉ mới bắt đầu suy nghĩ theo cách này ...) –

0

Bây giờ, nó thậm chí không nên biên dịch. Biểu thức lambda tạo ra một kiểu (một hàm functor). Không có chuyển đổi ẩn từ kiểu sang con trỏ hàm.

Tùy thuộc vào trình biên dịch, chức năng main có thể có liên kết C++ hoặc C (được thực hiện được xác định). Biểu thức Lambda trả về kiểu C++ với toán tử gọi hàm, do đó liên kết C++.

+0

Có thực sự là một chuyển đổi tiềm ẩn từ một lambda không bắt đến một con trỏ hàm. – avakar

+0

Trích dẫn: (5.1.2/6). –

+0

Cả hai đều đúng. Mặc dù, nó ngầm chuyển đổi thành con trỏ thành hàm thành viên, không phải là một hàm miễn phí. Mơ hồ nhớ rằng có thể đã nhầm lẫn tôi. – mloskot

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