2015-03-11 12 views
9

Mặc dù chủ đề được thảo luận nhiều lần, tôi vẫn chưa tìm thấy câu trả lời thỏa mãn nào. Khi nào cần trả lại dữ liệu từ một hàm bằng cách trả về hoặc để chuyển một tham chiếu để thay đổi dữ liệu trên địa chỉ? Câu trả lời cổ điển là chuyển một biến như tham chiếu đến một hàm khi nó trở nên lớn (để tránh việc sao chép ngăn xếp). Điều này có vẻ đúng đối với bất kỳ thứ gì như cấu trúc hoặc mảng. Tuy nhiên việc trả về một con trỏ từ một hàm không phải là không phổ biến. Trong thực tế, một số chức năng từ thư viện C đến chính xác. Ví dụ:C: Khi nào cần trả lại theo giá trị hoặc vượt qua tham chiếu

char *strcat(char *dst, const char *src); 

Luôn trả về con trỏ đến đích ngay cả khi có lỗi. Trong trường hợp này, chúng ta chỉ có thể sử dụng biến được truyền và để lại cho nó là gì (như hầu hết).

Khi xem cấu trúc, tôi thấy điều tương tự xảy ra. Tôi thường trả về con trỏ khi các hàm chỉ cần được sử dụng trong khởi tạo biến.

char *p = func(int i, const char *s); 

Sau đó, có đối số rằng các biến đối phó ngăn xếp là tốn kém và do đó, để sử dụng con trỏ thay thế. Nhưng như đã đề cập, here một số trình biên dịch có thể tự quyết định điều này (giả sử điều này cũng xảy ra với C). Có quy tắc chung hay ít nhất là một số quy ước bất thành văn khi sử dụng cái này hay cái kia? Tôi đánh giá cao hiệu suất trên thiết kế.

+3

Âm thanh giống như http://programmers.stackexchange.com/ question – cup

+0

Con trỏ trở lại thường dẫn đến vấn đề quản lý suốt đời đối tượng được trỏ đến, vì 90% thời gian, điểm mốc được xây dựng mới bởi hàm. – user3528438

+0

Ví dụ với 'strcat' là đúng đối với API kiểu cũ. Mã lỗi trả về thay thế mới: 'errno_t strcat_s ( char * strDestination, size_t numberOfElements, const char * strSource )'. – i486

Trả lời

10

Bắt đầu bằng việc quyết định phương pháp làm cho ý nghĩa nhất ở cấp logic, không phụ thuộc vào những gì bạn nghĩ những tác động hiệu suất có thể. Nếu trả lại struct theo giá trị, hãy chuyển tải rõ ràng mục đích của mã, sau đó thực hiện điều đó.

Đây không phải là những năm 1980 nữa. Các trình biên dịch đã trở nên thông minh hơn rất nhiều kể từ đó và thực hiện tốt công việc tối ưu hóa mã, đặc biệt là mã được viết một cách rõ ràng và đơn giản. Tương tự, việc truyền tham số và các quy ước trả về giá trị cũng trở nên khá phức tạp. Mô hình dựa trên nền tảng đơn giản không thực sự phản ánh thực tế của phần cứng hiện đại.

Nếu ứng dụng kết quả không đáp ứng các tiêu chí hiệu suất của bạn, hãy chạy nó thông qua một trình hồ sơ để tìm các nút cổ chai.Nếu hóa ra trả lại rằng struct theo giá trị đang gây ra sự cố, thì bạn có thể thử nghiệm bằng cách chuyển qua tham chiếu đến hàm.

Trừ khi bạn đang làm việc trong một môi trường được nhúng cao, bị hạn chế, bạn thực sự không phải tính từng chu kỳ byte và CPU. Bạn không muốn lãng phí không cần thiết, nhưng bởi cùng một mã thông báo bạn không muốn bị ám ảnh về cách mọi thứ hoạt động ở mức thấp trừ khi a) bạn có yêu cầu thực sự nghiêm ngặt và b) bạn là intimately quen thuộc với chi tiết về nền tảng cụ thể của bạn (có nghĩa là bạn không chỉ biết chức năng gọi điện của nền tảng của bạn trong và ngoài, bạn biết trình biên dịch của bạn sử dụng các quy ước đó như thế nào). Nếu không, bạn chỉ đoán thôi. Hãy để trình biên dịch thực hiện công việc khó khăn cho bạn. Đó là những gì nó có cho.

-2

Quy tắc ngón tay cái:

  1. Nếu sizeof(return type) lớn hơn sizeof(int), có lẽ bạn nên vượt qua nó bằng con trỏ để tránh những phí bản sao. Đây là vấn đề hiệu suất. Có một số hình phạt cho dereferencing con trỏ, do đó, có một số ngoại lệ cho quy tắc này.
  2. Nếu kiểu trả về phức tạp (chứa thành viên con trỏ), hãy chuyển nó qua con trỏ. Việc sao chép giá trị trả về cục bộ vào ngăn xếp sẽ không sao chép bộ nhớ động, ví dụ.
  3. Nếu bạn muốn chức năng cấp phát bộ nhớ, nó sẽ trả về con trỏ đến bộ nhớ mới được cấp phát. Nó được gọi là nhà máy mẫu thiết kế.
  4. Nếu bạn có nhiều thứ bạn muốn trả về từ một hàm - trả về một giá trị, và chuyển phần còn lại theo con trỏ.
  5. Nếu bạn có loại dữ liệu phức tạp/lớn, cả đầu vào lẫn đầu ra, hãy chuyển nó qua con trỏ.
+1

Chúng đến từ đâu? Tôi có nghĩa là 'Quy tắc ngón tay cái' của bạn. Bạn có thể trình bày các liên kết tham chiếu không? –

+0

Trải nghiệm của tôi, một số ý thức phổ biến và thực hành tốt trong ngành. – liorda

+0

Không 5 áp dụng cho bất kỳ loại dữ liệu nào ... và đây là ít nhất các câu trả lời chưa hoàn chỉnh mà bạn cung cấp ở đây .... – Pandrei

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