2016-01-27 21 views
6

Tôi biết sự khác biệt giữa việc truyền theo giá trị, tham chiếu hoặc con trỏ trong trường hợp chung. Tuy nhiên, câu hỏi của tôi là về trường hợp đặc biệt về một container với cấu trúc đơn giản.Việc chuyển vùng chứa theo giá trị hoặc tham chiếu

Giả sử trường hợp này:

class image{ 
    image()=default; 
    image(image const&)=default; 
    ~image()=default; 

    int w; 
    int h; 
    uchar* data; 
} 

Khi đi qua một đối tượng của lớp này những gì sao chép chỉ hai số nguyên là gì và con trỏ không phải là toàn bộ dữ liệu. Trong trường hợp này là có mục đích để vượt qua nó bằng cách tham khảo? Hoặc là có một mục đích để không vượt qua nó bằng cách tham khảo?

Điều kích hoạt câu hỏi này là tôi đã đọc rằng iterators trong C++ được thiết kế để có ánh sáng và được truyền theo giá trị. Vì vậy, tôi nghĩ rằng khái niệm này có thể được áp dụng cho các lớp đại diện cho một container để dữ liệu thực tế không có dữ liệu.

+1

Dữ liệu 'uchar * 'là gì? Tôi có nghĩa là nó là một nguồn lực để sao chép sâu và làm sạch? – Jarod42

+0

khi sao chép (không nhân bản) chỉ con trỏ sẽ được sao chép và cả hai đối tượng sẽ chia sẻ cùng một dữ liệu thực tế –

+0

liên quan: http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three –

Trả lời

6

Imho, các hướng dẫn tốt nhất về cách vượt qua đối số có thể tìm thấy trong thảo luận tuyệt vời của Herb Sutters Back to the Basics! Essentials of Modern C++ Style. Trong trường hợp cụ thể của bạn, đi qua giá trị sẽ là lựa chọn tốt nhất, vì cấu trúc của bạn rẻ để sao chép.

cpp parameter passing overview.

+0

Bạn thậm chí có thể lập luận rằng cấu trúc này cũng "rẻ để di chuyển" - đặc biệt nếu nó có một con trỏ được quản lý như 'unique_ptr' được đảm bảo để hỗ trợ di chuyển đúng và đề xuất chuyển nó theo tham chiếu. Tôi nghĩ rằng ví dụ cụ thể này quá nhỏ nên cả hai đối số/quyết định đều có giá trị như nhau. – CompuChip

+0

Nó không chỉ là chi phí sao chép quan trọng; các đối tượng riêng biệt có được nhiều cơ hội tối ưu hóa hơn vì trình biên dịch được phép giả định rằng không có gì khác có thể trỏ/tham chiếu đến đối tượng đó. Ví dụ: ' int gi; int val (int i) { \t gi + = i; \t gi + = i; \t trả lại i; } int ref (const int & i) { \t gi + = i; \t gi + = i; \t trả lại i; } int main() { \t gi = 2; \t std :: cout << val (gi) << std :: endl; // kết quả đầu ra 2 \t gi = 2; \t std :: cout << ref (gi) << std :: endl; // đầu ra 8 } ' Trong ref(), trình biên dịch không thể giả định giá trị của tôi không thay đổi. – Nevin

5

Với hàm tạo bản sao mặc định, mọi bản sao sẽ cạn và sẽ không tạo bản sao của bộ nhớ được chỉ thành bởi data. Vì vậy, khi bạn chuyển qua tham chiếu, chỉ có hai số nguyên và con trỏ sẽ được chuyển, với tổng số khoảng 12 bytes (tùy thuộc vào kiến ​​trúc của bạn, tức là kích thước con trỏ).

Sự khác biệt đó quá nhỏ, đến mức nó không quan trọng cho dù bạn truyền nó theo giá trị hay tham chiếu. Sau này có thể là hơi nhanh hơn vì con trỏ có thể luôn luôn được chuyển qua qua thanh ghi CPU và 12 byte có thể không phải là, nhưng đó thực sự là tối ưu hóa vi mô.

Cá nhân tôi chuyển bất kỳ thứ gì trừ các kiểu nguyên thủy theo (const) tham chiếu, theo mặc định, trừ khi tôi có lý do không (xem jupp0r's answer). Ưu điểm chính trong quá trình phát triển là khi lớp học phát triển, tôi không phải lo lắng khi nào nó trở thành quá lớn và thay đổi tất cả các chức năng của tôi để vượt qua bằng tham chiếu.

Theo như trình lặp C++ mặc định, hãy lưu ý rằng chúng là có nghĩa là về cơ bản chỉ là con trỏ. Trong thực tế, tôi biết rằng đối với Microsoft Visual C++ biên dịch trong chế độ phát hành với tối ưu hóa được kích hoạt, vòng lặp cho các cấu trúc dữ liệu liền kề như std::vector sẽ giảm xuống chỉ như vậy. Tôi không biết nếu các trình biên dịch khác làm điều này là tốt, tôi sẽ nghĩ như vậy. Tuy nhiên, bạn sẽ nhận thấy rằng nếu bạn vô hiệu hóa tối ưu hóa, thì đột nhiên có sự khác biệt giữa việc viết số it++++it với gia số vòng lặp, ví dụ - hoàn toàn là do thao tác sao chép bổ sung trong trường hợp trước đó. Vì vậy, ngay cả "rẻ để sao chép" có thể có tác động nếu bạn làm điều đó thường xuyên đủ. Như thường lệ: khi lo lắng về hiệu suất, đo lường và quyết định dựa trên các con số.

+0

Các bộ lặp cho bất kỳ thứ gì ngoài cấu trúc dữ liệu liền kề không thể giảm xuống chỉ với các con trỏ, vì chúng có các ngữ nghĩa khác nhau. – Nevin

+0

Cảm ơn @Nevin, đã chỉnh sửa. – CompuChip

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