2008-10-26 61 views
55

Trong một số mã tôi đã kế thừa, tôi thấy việc sử dụng thường xuyên size_t với vòng loại không gian tên std. Ví dụ:Có phải "std :: size_t" có ý nghĩa trong C++ không?

std::size_t n = sizeof(long); 

Nó biên dịch và chạy tốt, tất nhiên. Nhưng nó có vẻ như thực hành xấu với tôi (có lẽ được chuyển từ C?).

Có đúng là size_t được tích hợp vào C++ và do đó trong không gian tên chung? Tệp tiêu đề có cần sử dụng size_t trong C++ không?

Một cách khác để đặt câu hỏi này là chương trình sau đây (với no bao gồm) được mong đợi là biên dịch trên tất cả trình biên dịch C++ không?

size_t foo() 
{ 
    return sizeof(long); 
} 
+9

C không có không gian tên. – wnoise

+1

Nó được tích hợp vào C++, khi bạn #include và nằm trong vùng tên không gian. Xem câu trả lời của tôi dưới đây. –

+2

Nó không phải là 'một cách khác để đặt câu hỏi này' - đó là một câu hỏi khác: lợi nhuận chính int. – fizzer

Trả lời

126

Dường như có sự nhầm lẫn giữa đám đông stackoverflow liên quan này

::size_t được định nghĩa trong tiêu đề tương thích ngược stddef.h. Nó là một phần của ANSI/ISO CISO C++ kể từ khi bắt đầu. Mọi việc triển khai C++ phải giao hàng với stddef.h (khả năng tương thích) và cstddef trong đó chỉ định nghĩa sau này xác định std::size_t và không nhất thiết phải là ::size_t. Xem Phụ lục D của Tiêu chuẩn C++.

+12

Hoàn toàn là câu trả lời tốt nhất ở đây. Nó dựa trên tiêu chuẩn thay vì một trình biên dịch cụ thể. Nó trả lời câu hỏi ban đầu mà không đi lạc xuống tangents. – Darryl

+2

Một lý do khác để không sử dụng 'using namespace std' –

+0

@Darryl: Để công bằng, tất cả các câu trả lời cũ cũng đã làm như vậy. –

2

Đôi khi các thư viện khác sẽ xác định size_t của riêng chúng. Ví dụ tăng. std :: size_t xác định rằng bạn chắc chắn muốn một tiêu chuẩn C++.

size_t là loại tiêu chuẩn C++ và được xác định trong không gian tên std.

+0

Điều đó có ý nghĩa. Bạn có biết nếu ":: size_t" hoặc "std :: size_t" (hoặc có lẽ cả hai) là một phần của thông số ngôn ngữ? – jwfearn

4

size_t không được tích hợp vào C++. Và nó không được định nghĩa theo mặc định. Cái này không biên dịch với GCC:

int main(int argc, char** argv) { 
size_t size; 
} 

Điều đó nói rằng, size_t là một phần của POSIX và nếu bạn sử dụng những thứ chỉ cơ bản như <cstdlib>, bạn sẽ có khả năng kết thúc có nó được xác định.

Bạn có thể tranh luận rằng tiêu chuẩn :: size_t là tương đương C++ của size_t. Như Brian đã chỉ ra, std :: được sử dụng như không gian tên để tránh thiết lập các biến toàn cầu không phù hợp với tất cả mọi người. Nó giống như std :: string, cũng có thể được định nghĩa trong không gian tên gốc.

41

Mục 17.4.1.2 của chuẩn C++, khoản 4, khẳng định rằng:

"Trong Thư viện chuẩn C++, tuy nhiên, tờ khai và định nghĩa (ngoại trừ tên được định nghĩa là các macro trong C) nằm trong phạm vi không gian tên (3.3.5) của không gian tên std. "

này bao gồm vật phẩm tìm thấy trong tiêu đề của mô hình cname, bao gồm cstddef, trong đó xác định size_t.

Vì vậy, tiêu chuẩn :: size_t thực tế là chính xác.

13

Bạn có thể nhận được size_t trong không gian tên chung bằng cách bao gồm, ví dụ: <stddef.h> thay vì <cstddef>. Tôi không thể thấy bất kỳ lợi ích rõ ràng nào và tính năng này không còn được dùng nữa.

+0

Một số lời giải thích của downvote sẽ lịch sự. Câu trả lời là đúng và về chủ đề. – fizzer

+0

Tôi không biết ai đã bỏ phiếu cho bạn. Quan sát của bạn rất quan trọng đối với câu hỏi ban đầu. –

+0

Tôi đã bỏ phiếu bạn xuống, chủ yếu là vì có cách không dùng nữa để thực hiện việc này: sử dụng khai báo, tức là 'sử dụng std :: size_t' và bạn không đề cập đến điều này như một giải pháp thay thế tốt hơn. :-) – cic

1

Các tiêu đề biên dịch GNU chứa một cái gì đó giống như

typedef long int __PTRDIFF_TYPE__; 
typedef unsigned long int __SIZE_TYPE__;

Sau đó stddef.h constains cái gì đó như

typedef __PTRDIFF_TYPE__ ptrdiff_t; 
typedef __SIZE_TYPE__ size_t;

Và cuối cùng là tập tin cstddef chứa một cái gì đó giống như

 
#include <stddef.h> 

namespace std { 

    using ::ptrdiff_t; 
    using ::size_t; 

} 

Tôi nghĩ rằng nên làm rõ. Miễn là bạn bao gồm <cstddef>, bạn có thể sử dụng size_t hoặc std :: size_t vì size_t được nhập vào bên ngoài vùng tên std và sau đó được bao gồm. Có hiệu quả bạn có

typedef long int ptrdiff_t; 
typedef unsigned long int size_t; 

namespace std { 

    using ::ptrdiff_t; 
    using ::size_t; 

} 
+0

Vì vậy, GNU định nghĩa nó theo cách đó, không điều đó có nghĩa là tất cả các trình biên dịch đều làm gì? Liệu tiêu chuẩn nói nó phải như vậy? – anthropomorphic

2

Tôi nghĩ rằng các giải thích rõ ràng là đủ. Các std::size_t làm cho tinh thần tốt trong C + + và ::size_t làm cho (ít nhất) ý thức tốt trong C.

Tuy nhiên vẫn còn một câu hỏi. Cụ thể là liệu an toàn để giả định rằng ::size_tstd::size_t có tương thích không?

Từ góc độ an toàn thuần túy, chúng không nhất thiết phải giống nhau trừ khi được xác định ở đâu đó mà chúng phải giống hệt nhau.

Tôi nghĩ rằng nhiều người đang sử dụng một cái gì đó a la:

---- 
// a.hpp 
#include <string> 

void Foo(const std::string & name, size_t value); 

----- 
// a.cpp 
#include "a.hpp" 

using namespace std; 

void Foo(const string & name, size_t value) 
{ 
    ... 
} 

Vì vậy, trong phần đầu bạn defintely sử dụng ::size_t trong khi trong file nguồn mà bạn sẽ sử dụng std::size_t. Vì vậy, họ phải tương thích, phải không? Nếu không, bạn sẽ nhận được một lỗi trình biên dịch.

/Michael S.

+2

:: size_t không có ý nghĩa trong C, không có không gian tên. –

4
std::size_t n = sizeof(long); 

Trên thực tế, bạn đã không hỏi cụ thể những gì dường như là một thói quen xấu int trên. Sử dụng size_t, giấy chứng nhận với không gian tên std, ...

Khi tiêu chuẩn C++ cho biết (18.1), size_t là một loại được xác định trong tiêu đề chuẩn. Tôi khuyên bạn nên bỏ bất kỳ suy nghĩ và ấn tượng nào về khả năng kế thừa từ ngôn ngữ C. C++ là một ngôn ngữ riêng biệt và khác biệt và tốt hơn nên xem xét nó như vậy. Nó có thư viện chuẩn riêng và tất cả các phần tử của Thư viện chuẩn C++ được định nghĩa trong không gian tên std. Tuy nhiên, có thể sử dụng các phần tử của Thư viện chuẩn C trong chương trình C++.

Tôi muốn xem xét việc bao gồm một bản hack bẩn. Tiêu chuẩn C++ cho biết nội dung của các phần đầu là giống nhau hoặc dựa trên các tiêu đề tương ứng từ Thư viện chuẩn C, nhưng trong một số trường hợp, các thay đổi đã được áp dụng. Nói cách khác, nó không phải là một bản sao trực tiếp & dán các tiêu đề C vào tiêu đề C++.

size_t không phải là loại được tích hợp trong C++. Nó là một kiểu được định nghĩa để xác định kiểu kiểu tích phân nào được sử dụng như kiểu trả về của toán tử sizeof(), vì kiểu trả về thực tế của sizeof() được định nghĩa thực hiện, vì vậy tiêu chuẩn C++ hợp nhất bằng cách định nghĩa size_t.

chương trình sau đây (không có bao gồm) dự kiến ​​sẽ biên dịch trên tất cả trình biên dịch C++?

size_t foo() 
{ 
    return sizeof(long); 
} 

CáC++ Chuẩn C nói (1.4):

Các tên được định nghĩa trong thư viện có phạm vi không gian tên (7.3). Một đơn vị dịch C++ (2.1) nhận được quyền truy cập vào các tên này bằng cách bao gồm tiêu đề thư viện chuẩn thích hợp (16.2).

Size_t là tên được xác định trong không gian tên std, vì vậy mọi chương trình sử dụng tên này phải bao gồm tiêu đề tương ứng, trong trường hợp này.

Tiếp theo, chương 3.7.3 nói:

Tuy nhiên, đề cập đến tiêu chuẩn, std :: bad_alloc, và std :: size_t là vô hình thành trừ khi tên đã được tuyên bố bằng cách bao gồm các tiêu đề thích hợp.

Cho rằng, chương trình sử dụng size_t nhưng không bao gồm tiêu đề là không đúng định dạng.

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