2008-12-02 37 views
11

Chúng tôi có thư viện C++ mà chúng tôi cung cấp cho một số khách hàng khác nhau. Gần đây, chúng tôi đã thực hiện chuyển đổi từ việc sử dụng con trỏ thô trong giao diện công khai để sử dụng tăng :: sharedptr thay thế. Điều này đã cung cấp một lợi ích to lớn, như bạn có thể đoán, trong đó bây giờ các khách hàng không còn phải lo lắng về những người cần phải xóa những gì và khi nào. Khi chúng tôi thực hiện công tắc, tôi tin rằng đó là điều đúng để làm, nhưng nó làm tôi bực mình vì chúng tôi phải đưa thứ gì đó từ thư viện của bên thứ ba vào giao diện công cộng của chúng tôi - nói chung là bạn tránh điều đó nếu có thể. Tôi đã hợp lý hoá nó rằng việc tăng cường thực tế là một phần của ngôn ngữ C++ bây giờ, và trường hợp sử dụng của chúng ta yêu cầu cả mã máy khách lẫn thư viện giữ các con trỏ tới các đối tượng. Tuy nhiên gần đây, một trong những khách hàng của chúng tôi đã hỏi chúng tôi liệu chúng tôi có thể chuyển sang sử dụng lớp con trỏ thông minh trung tính trong giao diện hay không, vì thư viện của chúng tôi về cơ bản đang buộc họ vào một phiên bản cụ thể - một điểm mà tôi chắc chắn hiểu và đánh giá cao. Vì vậy, bây giờ tôi tự hỏi những gì các khóa học tốt nhất của hành động có thể được. Tôi đã suy nghĩ về nó một chút, và tự hỏi về việc tạo ra một lớp con trỏ thông minh đơn giản mà chỉ đơn giản là tổ chức một con trỏ thông minh tăng thực sự. Nhưng sau đó các khách hàng có lẽ sẽ ngay lập tức nhồi nhét một trong những thứ đó vào hương vị của họ về tăng :: sharedptr, và sau đó chúng tôi sẽ là ba con trỏ được chia sẻ sâu - có thể là một vấn đề, hoặc có thể không. Dù sao, tôi rất muốn nghe một số ý kiến ​​từ cộng đồng về cách tốt nhất để giải quyết vấn đề này.Sử dụng tăng cường :: shared_ptr trong giao diện công cộng của thư viện

Chỉnh sửa: Ban đầu tôi đã nói chuyển quyền sở hữu, nhưng tôi nên đã chỉ định mã đó trên cả hai mặt của ranh giới API cần giữ con trỏ đến đối tượng.

Trả lời

13

shared_ptr <> một phần của ngôn ngữ, kể từ khi phát hành TR1. Xem: (TR1)

+1

Có, nhưng chúng tôi không thể buộc khách hàng của chúng tôi chuyển sang Visual Studio 2008, trong đó có TR1, IIRC. Một số vẫn còn trên VS 2005. –

+1

Bạn có thể bao gồm thư mục Boost TR1 với tiêu đề thư viện của mình không? Tôi phải xem xét giấy phép để xem liệu đó có phải là hợp pháp hay không, nhưng có lẽ nó là như vậy. Ngoài ra, kể từ khi tăng :: shared_ptr <> chỉ đơn giản là một mẫu, không có thư viện được chia sẻ hoặc tĩnh là cần thiết. –

+2

Lưu ý rằng TR1 không phải là một phần của ngôn ngữ như vậy, nhưng đó là một bộ sưu tập các thư viện thông tin (chính thức) có thể là một phần của tiêu chuẩn ngôn ngữ trong tương lai. Xem tại đây: http://www.iso.org/iso/standards_development/processes_and_procedures/deliverables/iso_tr_deliverable.htm –

4

Đây là C++. Bạn biết đấy, bạn có thể tạo mẫu cho lớp giao diện qua việc thực hiện con trỏ được chia sẻ.

+2

... do đó làm cho nó không thể che giấu việc triển khai giao diện của bạn vì tất cả chúng đều cần phải là mẫu. Không phải là một ý kiến ​​hay đối với một người nào đó đang cố gắng bán phần mềm sở hữu độc quyền – Bklyn

+0

@Bklyn: Tôi không dám sử dụng thư viện C++ của bên thứ ba mà không có nguồn đóng gói ít nhất. Các C + + ABI chỉ là quá mong manh. – Joshua

6

Nếu ngữ nghĩa thực sự là chuyển quyền sở hữu, tại sao không sử dụng auto_ptr vì nó là tiêu chuẩn C++? Bên trong, bạn vẫn có thể xây dựng shared_ptr của bạn từ auto_ptr và sau đó đã chia sẻ quyền sở hữu nếu bạn cần.

3

Bạn có thể sử dụng tiện ích boost copy để tạo phiên bản tăng tùy chỉnh chỉ có lớp con trỏ thông minh. Vì lớp con trỏ thông minh là thư viện chỉ tiêu đề, điều này sẽ dẫn đến một vài tiêu đề mà bạn có thể đưa vào thư viện của mình.

18

Một giải pháp khả thi là tăng cường tàu :: shared_ptr với dự án của bạn. Vì tất cả đều bao gồm các tiêu đề, điều này sẽ giải phóng khách hàng của bạn khỏi phải cài đặt các thư viện tăng theo cách thủ công. Bạn có thể sử dụng bcp để nhận tất cả các tệp cần thiết bởi một thư viện tăng cụ thể, bao gồm cả các thư viện. Tôi đã làm điều đó khi tôi làm việc cho một công ty trở lại sau đó và cần boost::shared_ptr và nó thực sự làm việc rất nhiều.

3

Đây là một câu hỏi thú vị mà tôi đã có một thời gian. Bạn có buộc người dùng của bạn vào bất kỳ thư viện nào bạn cung cấp hay cho họ quyết định điều gì là tốt nhất trong dự án của họ? Như mọi khi, câu hỏi là những gì bạn đang cung cấp và những gì bạn đang yêu cầu từ người dùng.

Nếu bạn sử dụng con trỏ thô, bạn cho phép tất cả các loại khả năng. Mã người dùng có thể sử dụng một con trỏ thô, lưu trữ nó thành std :: auto_ptr, shared_ptr (cho dù tăng hoặc TR1), hoặc phiên bản homebrewed của một con trỏ thông minh. Nhưng điều này cũng có thể khiến người dùng gặp rắc rối nếu họ quên giải phóng bộ nhớ, và nó đòi hỏi một số mã ở phía họ nếu họ chỉ muốn tạo tạm thời cho một cuộc gọi phương thức (nếu bạn cung cấp con trỏ thô, họ sẽ phải lưu trữ con trỏ trong một biến con trỏ không thể tạm thời [có thể thông minh]).

Bây giờ, nếu bạn sử dụng con trỏ thông minh, bạn đang buộc giải pháp của mình vào người dùng. Nếu họ có kế hoạch sử dụng phiên bản riêng của một con trỏ thông minh (nói rằng bạn sử dụng boost :: shared_ptr và họ muốn std :: tr1 :: shared_ptr) họ không còn được phép sử dụng nó nếu họ làm việc với giao diện của bạn. Dù con trỏ thông minh bạn quyết định khi nào (ngoài std :: auto_ptr đặc biệt), bạn không chỉ ép buộc một giải pháp mà còn là vấn đề mà nó có.

Nếu người dùng của bạn có ứng dụng đa luồng và giải pháp của bạn không phải là chủ đề an toàn, người dùng bị ràng buộc vào một giải pháp không an toàn. Mặt khác, nếu con trỏ thông minh là luồng an toàn nhưng chi phí khóa thì chi phí đó sẽ được đẩy tới người dùng của bạn ngay cả khi chúng hoạt động trong ứng dụng đa luồng. Nếu bạn biên dịch thư viện của bạn (không phải là phần đầu lib) thì bạn không chỉ là kiểu con trỏ thông minh mà còn là một phiên bản cụ thể của nó, vì bất kỳ thay đổi nào trong thư viện con trỏ thông minh sẽ phá vỡ tính tương thích của mã của bạn.

Lưu ý phụ, tăng :: shared_ptr (tăng 1.33+) là thread safe trong hầu hết các trường hợp và sử dụng triển khai không khóa trong nhiều nền tảng. Dù sao điều này sẽ cung cấp cho bạn một ý tưởng về những điều bạn nên xem xét.

Cuối cùng, bạn phải xem xét rằng bạn không chỉ ràng buộc người dùng sử dụng loại con trỏ thông minh của bạn, mà còn là phiên bản tương tự của nó. Nếu bạn biên dịch lib của bạn chống lại một phiên bản cụ thể, người dùng sẽ bị ràng buộc với việc triển khai cụ thể đó là

6

Trước hết, nếu bạn phân phối thư viện dưới dạng mã nguồn chứ không phải là thư viện được biên dịch, bạn có thể bỏ qua câu trả lời này. Ngoài ra còn có một số vấn đề cụ thể của cửa sổ có thể không liên quan đến các nền tảng khác.

Cá nhân tôi nghĩ bạn nên tránh có quá nhiều cồng kềnh C++ trong giao diện công cộng của thư viện vì nó có thể gây ra rất nhiều vấn đề ở khách hàng.

Tôi không chắc điều này có thể áp dụng cho ví dụ cụ thể của bạn, nhưng cá nhân tôi gặp phải sự cố khi biểu tượng từ thư viện stl mà tôi sử dụng xung đột với thư viện bên thứ ba khi tôi nâng cấp lên phiên bản mới . Điều này có nghĩa là chúng tôi đã gặp sự cố ở những nơi xa lạ và tôi phải thực hiện rất nhiều thủ thuật để tránh sự cố. Cuối cùng tôi ở lại với phiên bản cũ của thư viện vì điều này. Một vấn đề khác mà bạn có thể gặp phải là các trình biên dịch C++ khác nhau có thể mang các ký hiệu giống nhau, có nghĩa là bạn có khả năng cần cung cấp một thư viện riêng cho mọi trình biên dịch bạn muốn hỗ trợ ngay cả khi chúng sử dụng cùng phiên bản Boost. Kiểm tra cuốn sách "Hoàn hảo C++" để thảo luận về điều này. Trong thế giới hiện tại của các trình biên dịch và môi trường C++ khác nhau, tôi nghĩ rằng bạn nên tránh có bất cứ điều gì ngoài C trong giao diện của bạn và đảm bảo bạn liên kết thư viện của bạn một cách động (để tránh xung đột khi liên kết khách hàng của bạn liên kết thư viện của bạn , thư viện thời gian chạy Windows có thể là một nỗi đau thực sự ở đây). Bạn vẫn có thể sử dụng tăng cường và càng nhiều C++ ưa thích ở bên trong thư viện của bạn như bạn muốn vì tất cả các ký hiệu của bạn sẽ bị cô lập khỏi môi trường khách hàng của bạn trong dll.

Nếu bạn thực sự muốn có con trỏ thông minh và chức năng đẹp khác của C++ trong giao diện thư viện của bạn, hãy tạo lớp tiện lợi mà bạn phân phối mã nguồn. Điều này sẽ đảm bảo nó luôn được biên dịch trong môi trường khách hàng. Giao diện này sau đó gọi các hàm C tiếp xúc của bạn theo những cách thông minh. Tôi không nghĩ rằng nên sử dụng boost trong lớp đó vì nó sẽ buộc khách hàng của bạn chấp nhận nó ngay cả khi họ không muốn, tuy nhiên thật dễ dàng để thay thế nó hoặc tìm giải pháp khác vì lớp đó được phân phối dưới dạng nguồn mã.

Một tính năng thú vị khác là dễ dàng gọi hàm C trong dll hơn hàm C++ với mang tên lạ nếu bạn muốn hiển thị thư viện của mình sang các ngôn ngữ khác với C/C++.

Cách tiếp cận này chắc chắn làm cho cuộc sống của bạn trở nên phức tạp hơn theo nhiều cách, nhưng đó là cách khiến mọi người tránh thư viện của bạn ít hơn vì không thể liên kết thành công với mã của riêng họ.

1

giới thiệu tăng :: shared_ptr buộc khách hàng của bạn sử dụng tăng. với một số người, đây là một vấn đề nhỏ.

nó cũng buộc khách hàng của bạn sử dụng cùng một trình biên dịch như được sử dụng bởi lib của bạn, nếu lib của bạn được phân phối dưới dạng nhị phân đã biên dịch. hoặc, nếu thư viện của bạn được phân phối trong mã nguồn, khách hàng phải dính vào lựa chọn của họ về trình biên dịch được sử dụng để biên dịch lib của bạn. đây không phải là vấn đề nhỏ đối với bất kỳ dự án có quy mô đáng kể nào.

1

Sử dụng auto_ptr hoặc gắn vào giao diện C. Buộc C++ libs vào giao diện của bạn luôn luôn xấu xí, giết chết bất kỳ cơ hội được nền tảng chéo, và gây ra một cơn ác mộng bảo trì cho khách hàng với cấu hình "hạ lưu" khác nhau.

Ngay khi C++ 0x đủ chính thống cho khách hàng của bạn, hãy chuyển sang std::shared_ptr.

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