2010-07-30 33 views
8

Hãy nói rằng chúng tôi có một lớp trông như thế này:Cấu trúc bộ nhớ của đối tượng chỉ có chức năng?

class A 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 

     int a; 
     int b; 
}; 

Bây giờ, tôi biết rằng đối tượng của lớp này sẽ được đặt ra trong bộ nhớ chỉ với hai ints. Tức là, nếu tôi tạo một vectơ các cá thể của lớp A, sẽ có hai ints cho một cá thể, sau đó theo sau là hai ints cho ví dụ thứ hai vv. Các đối tượng là POD.

NHƯNG giả sử lớp trông như thế này:

class B 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 
}; 

gì làm đối tượng của cái nhìn lớp này như thế nào trong bộ nhớ? Nếu tôi điền vào một vectơ với các trường hợp B ... thì có gì trong vector? Tôi đã được thông báo rằng các hàm thành viên không thuộc ảo được kết thúc dưới dạng các hàm miễn phí ở đâu đó hoàn toàn không liên quan đến các cá thể của lớp mà chúng được khai báo (hàm ảo cũng vậy, nhưng các đối tượng lưu trữ vtable với các con trỏ hàm) . Rằng các hạn chế truy cập chỉ đơn thuần là ở cấp độ ngữ nghĩa "con người". Chỉ các thành viên dữ liệu của một lớp (và vtable v.v.) thực sự tạo nên cấu trúc bộ nhớ của các đối tượng.

Vì vậy, một lần nữa, đối tượng của lớp B trông giống như thế nào trong bộ nhớ? Có một số loại giá trị giữ chỗ không? Cái gì đó phải ở đó, tôi có thể lấy địa chỉ của vật thể. Nó phải trỏ đến một cái gì đó. Bất kể nó là gì, trình biên dịch có cho phép inline/tối ưu hóa các đối tượng này và xử lý các cuộc gọi phương thức như các cuộc gọi hàm bình thường miễn phí không? Nếu tôi tạo một vectơ của chúng và gọi cùng một phương thức trên mọi đối tượng, trình biên dịch có thể loại bỏ vectơ và thay thế nó chỉ bằng một loạt các cuộc gọi bình thường không?

Tôi chỉ tò mò thôi.

+0

Nó xảy ra với tôi rằng nếu bạn muốn một wrapper đóng gói cho các chức năng có * không gian * không gian, bạn có thể sử dụng một không gian tên thay vì một lớp. Ngoài ra, nếu bạn làm cho các thành viên hoạt động tĩnh, bạn không bao giờ cần phải khởi tạo một đối tượng để truy cập chúng một cách tương tự như vậy, nó sẽ mất không gian. – Clifford

Trả lời

7

Tất cả các đối tượng trong C++ được đảm bảo có sizeof> = 1 sao cho mỗi đối tượng sẽ có một địa chỉ duy nhất.

Tôi chưa thử, nhưng tôi đoán rằng trong ví dụ của bạn, trình biên dịch sẽ cấp phát nhưng không khởi tạo 1 byte cho mỗi đối tượng hàm trong mảng/vectơ.

4

Đối tượng của lớp này trông như thế nào trong bộ nhớ?

Hoàn toàn tùy thuộc vào trình biên dịch. Một thể hiện của một lớp rỗng phải có kích thước khác 0, do đó các đối tượng riêng biệt có các địa chỉ riêng biệt (trừ khi nó được khởi tạo làm lớp cơ sở của một lớp khác, trong trường hợp đó nó có thể chiếm không gian). Thông thường, nó sẽ bao gồm một byte uninitialised duy nhất.

Dù vậy, trình biên dịch có cho phép inline/tối ưu hóa các đối tượng này và coi các cuộc gọi phương thức như các cuộc gọi hàm bình thường không?

Có; trình biên dịch không phải tạo đối tượng trừ khi bạn làm điều gì đó giống như lấy địa chỉ của nó. Các đối tượng hàm rỗng được sử dụng khá nhiều trong Thư viện Chuẩn, vì vậy điều quan trọng là chúng không giới thiệu bất kỳ chi phí không cần thiết nào.

0

Mọi thứ tôi nói từ đây trở đi là phụ thuộc triển khai thực hiện - nhưng hầu hết các triển khai sẽ tuân thủ.

Nếu lớp có bất kỳ phương thức ảo nào, sẽ có một thành viên con trỏ vtable vô hình.Đó không phải là trường hợp với ví dụ của bạn tuy nhiên.

Có, trình biên dịch sẽ xử lý hàm thành viên gọi giống như cuộc gọi hàm miễn phí, một lần nữa trừ khi đó là hàm ảo. Ngay cả khi nó là một chức năng ảo, trình biên dịch có thể bỏ qua vtable nếu nó biết loại bê tông tại thời điểm cuộc gọi. Mỗi cuộc gọi sẽ vẫn phụ thuộc vào đối tượng, bởi vì có một tham số this vô hình với con trỏ của đối tượng được thêm vào cuộc gọi.

2

tôi thực hiện các thí nghiệm sau:

#include <iostream> 

class B 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 
}; 

int main() 
{ 
    std::cout << sizeof(B) ; 
} 

Kết quả là 1 (VC++ 2010)

Dường như với tôi rằng lớp thực sự đòi hỏi không có ký ức nào, nhưng điều đó một đối tượng không thể không có kích thước vì điều đó sẽ không có ý nghĩa ngữ nghĩa nếu bạn lấy địa chỉ của nó chẳng hạn. Điều này được sinh ra bởi câu trả lời của Ferruccio

5

Như Ferruccio đã nói, Tất cả các đối tượng trong C++ đều được đảm bảo có kích thước ít nhất 1. Hầu hết khả năng là 1 byte nhưng điền vào kích thước căn chỉnh. .

Tuy nhiên, khi sử dụng như một lớp cơ sở, nó không cần phải điền bất kỳ không gian, do đó:

class A {} a; // a is 1 byte. 
class B {} b; // b is 1 byte. 
class C { A a; B b;} c; // c is 2 bytes. 
class D : public A, B { } d; // d is 1 byte. 
class E : public A, B { char ee; } e; // e is only 1 byte 
0

tôi sẽ nghĩ rằng họ chỉ trông giống như bất kỳ các đối tượng trong C++:

  • Mỗi thể hiện của lớp chiếm không gian. Vì các đối tượng trong C++ phải có kích thước ít nhất là 1 (vì vậy chúng có các địa chỉ duy nhất, như Ferruccino đã nói), các đối tượng không chỉ định bất kỳ dữ liệu nào không được xử lý đặc biệt.
  • Chức năng không phải ảo không chiếm bất kỳ không gian nào trong một lớp. Thay vào đó, họ có thể được coi như các chức năng như thế này:

    int B_FuncA(B *this, int x); 
    int B_FuncB(B *this, int y); 
    

Nếu lớp này có thể được sử dụng bởi .cpp file khác, tôi nghĩ rằng chúng sẽ trở thành trường hợp lớp học thực tế, chứ không phải chức năng thông thường.

Nếu bạn chỉ muốn các chức năng của mình được tự do thay vì bị ràng buộc với các đối tượng, bạn có thể make them static hoặc use a namespace.

0

Tôi đã nói rằng chức năng thành viên phi ảo là vào cuối thập như các chức năng miễn phí ở đâu đó hoàn toàn không liên quan đến các trường hợp của lớp mà chúng được khai báo (chức năng ảo quá, nhưng các cửa hàng vật một vtable với con trỏ hàm). Rằng các hạn chế truy cập chỉ đơn thuần là ở cấp độ ngữ nghĩa "con người". Chỉ các thành viên dữ liệu của một lớp (và vtable v.v.) thực sự tạo nên cấu trúc bộ nhớ của các đối tượng.

Đúng, đó thường là cách hoạt động. Nó có thể là giá trị chỉ ra sự khác biệt rằng điều này không được quy định trong tiêu chuẩn, và nó không phải là yêu cầu - nó chỉ có ý nghĩa để thực hiện các lớp như thế này trong trình biên dịch.

Vì vậy, một lần nữa, đối tượng lớp B trông như thế nào trong bộ nhớ? Có một số loại giá trị giữ chỗ không?Có gì đó phải ở đó, tôi có thể lấy địa chỉ của đối tượng

Chính xác. :) Tiêu chuẩn C++ yêu cầu các đối tượng chiếm ít nhất một byte, cho chính xác lý do bạn nói. Nó phải có một địa chỉ, và nếu tôi đặt các đối tượng này vào một mảng, tôi phải có khả năng tăng một con trỏ để có được đối tượng "tiếp theo", vì vậy mọi đối tượng phải có một địa chỉ duy nhất và chiếm ít nhất 1 byte. (Tất nhiên, các đối tượng rỗng không để lấy chính xác 1 byte. Một số trình biên dịch có thể chọn tạo 4 byte hoặc bất kỳ kích thước nào khác, vì lý do hiệu suất)

Trình biên dịch hợp lý thậm chí sẽ không một giá trị giữ chỗ mặc dù. Tại sao bận tâm viết bất kỳ giá trị cụ thể vào một byte này? Chúng ta chỉ có thể để nó chứa bất cứ thứ gì nó được giữ lại khi đối tượng được tạo ra. Nó sẽ không bao giờ được truy cập anyway. Một byte đơn được cấp phát và không bao giờ đọc hoặc ghi vào.

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