Подтвердить что ты не робот

Использование boost:: shared_ptr в общем интерфейсе библиотеки

У нас есть библиотека С++, которую мы предоставляем нескольким различным клиентам. Недавно мы перешли от использования raw-указателей в публичном интерфейсе к использованию boost:: sharedptr. Это обеспечило огромную выгоду, как вы могли догадаться, в том, что теперь клиентам больше не нужно беспокоиться о том, кому нужно удалять то, что и когда. Когда мы сделали переключатель, я полагал, что это правильно, но меня беспокоило, что мы должны были включить что-то из сторонней библиотеки в наш публичный интерфейс - как правило, вы избегаете такого рода вещей, если можете. Я рационализировал это, что повышение было практически частью языка С++, и наш прецедент требует, чтобы и клиентский код, и библиотека удерживали указатели на объекты. Однако недавно один из наших клиентов спросил нас, можем ли мы переключиться на использование нейтрального класса интеллектуальных указателей в интерфейсе, потому что наша библиотека по существу вынуждает их к определенной версии boost-point, которую я, безусловно, понимаю и ценю. Так что теперь мне интересно, какой может быть лучший способ действий. Я немного подумал об этом и задался вопросом о создании простого класса интеллектуальных указателей, который просто содержал интеллектуальный указатель реального толчка. Но тогда клиенты, вероятно, сразу же добавят один из них в свой вкус boost:: sharedptr, а затем мы будем иметь три общих указателя в глубину - что может быть проблемой, а может и нет. Во всяком случае, я бы хотел услышать некоторые мнения сообщества о том, как наилучшим образом решить эту проблему.

Изменить: я изначально сказал о передаче права собственности, но я должен был указать, что код с обеих сторон границы API должен содержать указатель на объект.

4b9b3361

Ответ 1

shared_ptr < > является частью языка, начиная с выпуска TR1. Смотрите: (TR1)

Ответ 2

Одним из возможных решений является отправка boost:: shared_ptr с вашим проектом. Поскольку все это состоит из заголовков, это освободит ваших клиентов от необходимости устанавливать библиотеки boost вручную. Вы можете использовать bcp, чтобы получить все файлы, необходимые конкретной библиотеке boost, включая сами библиотеки. Я сделал это, когда я работал в компании тогда и нуждался в boost::shared_ptr, и он действительно сильно работал.

Ответ 3

Если семантика действительно является передачей прав собственности, почему бы не использовать auto_ptr, поскольку она является стандартным С++? Внутри вы все равно можете создать свой shared_ptr из auto_ptr, а затем получить совместное владение, если вам это нужно.

Ответ 4

Прежде всего, если вы распространяете свою библиотеку как исходный код, а не как скомпилированную библиотеку, вы можете игнорировать этот ответ. Также есть некоторые проблемы с конкретными окнами, которые могут не иметь отношения к другим платформам.

Я лично считаю, что вам следует избегать слишком большого количества флеш-c++ в публичном интерфейсе вашей библиотеки, поскольку это может вызвать множество проблем на клиенте.

Я не уверен, насколько это применимо к вашему конкретному примеру, но я лично столкнулся с проблемами, когда символы из библиотеки stl, которые я использовал, противоречили тем, которые были в третьей библиотеке, когда я обновился до новой версии. Это означало, что у нас были катастрофы в незнакомых местах, и мне пришлось делать много трюков, чтобы избежать проблемы. В конце концов я остался со старой версией библиотеки из-за этого.

Еще одна проблема, с которой вы можете столкнуться, заключается в том, что разные компиляторы С++ могут калечить одни и те же символы по-разному, что означает, что вам может понадобиться предоставить отдельную библиотеку для каждого компилятора, который вы хотите поддерживать, даже если они используют ту же версию Boost. Ознакомьтесь с книгой "Imperfect С++" для обсуждения этого вопроса.

В текущем мире разных компиляторов и сред С++ я считаю, что печальная правда заключается в том, что вам следует избегать наличия чего-либо, кроме C в вашем интерфейсе, и убедитесь, что вы динамически связываете свою библиотеку (чтобы избежать конфликтов при связывании ваших клиентов с вашей библиотекой, Windows runtime-библиотека может быть настоящей болью здесь). Вы все равно можете использовать boost и as much fancy С++ внутри своей библиотеки, поскольку вы хотите, чтобы все ваши символы были изолированы от среды ваших клиентов в dll.

Если вы действительно хотите иметь интеллектуальные указатели и другие приятные функциональные возможности С++ в интерфейсе вашей библиотеки, создайте удобный слой, для которого вы распространяете исходный код. Это гарантирует, что он всегда компилируется в среде клиентов. Этот интерфейс затем вызывает ваши открытые функции C умными способами. Я не думаю, что это хорошая идея использовать boost в этом слое, так как это заставит ваших клиентов принимать его, даже если они не хотят, однако его легко заменить или найти другое решение, поскольку этот слой распространяется как источник код.

Еще одна приятная особенность заключается в том, что проще всего вызывать функции C в dll, чем функции С++, с необычным названием mangling, если вы хотите выставить свою библиотеку на другие языки, кроме C/С++.

Этот подход определенно делает вашу жизнь более сложной во многих отношениях, но это способ сделать ее менее вероятной, чтобы люди избегали вашей библиотеки, потому что просто невозможно было правильно связать свой код.

Ответ 5

Это С++. Вы знаете, вы можете создать шаблон класса интерфейса по реализации общего указателя.

Ответ 6

Вы можете использовать утилиту boost copy для создания пользовательской версии boost, которая имела только класс интеллектуального указателя. Поскольку класс интеллектуального указателя представляет собой библиотеку только для заголовка, это должно привести к нескольким заголовкам, которые вы могли бы включить в свою библиотеку.

Ответ 7

Это интересный вопрос, который у меня был в течение некоторого времени. Вы вынуждаете своих пользователей в какую-либо библиотеку, которую вы предоставляете, или позволяете им решать, что лучше всего в их проекте? Как всегда, вопрос заключается в том, что вы предлагаете и чего вы требуете от пользователя.

Если вы используете raw-указатели, вы допускаете всевозможные возможности. Код пользователя может использовать необработанный указатель, хранить его в std:: auto_ptr, shared_ptr (будь то boost или TR1) или их домашняя версия умного указателя. Но это может также вызвать у пользователя проблемы, если они забудут освободить память, и для этого требуется еще один код на своей стороне, если они просто хотят, чтобы временный созданный для вызова метода (если вы предоставляете необработанные указатели, им нужно будет сохранить указатель в не временной (возможно, умной) переменной указателя).

Теперь, если вы используете интеллектуальный указатель, вы вынуждаете свое решение пользователю. Если они планируют использовать собственную версию умного указателя (скажем, вы используете boost:: shared_ptr, и они хотят std:: tr1:: shared_ptr), они больше не могут использовать его, если они работают с вашим интерфейсом. Какой бы умный указатель вы ни выбрали (помимо std:: auto_ptr, который является особым), вы не только заставляете решение, но и проблемы, которые он имеет.

Если у вашего пользователя многопоточное приложение, и ваше решение не является потокобезопасным, пользователь связан с небезопасным решением. Если, с другой стороны, интеллектуальный указатель является потокобезопасным, но при этом блокирует затраты, эти затраты подталкиваются к вашим пользователям, даже если они работают в многопоточном приложении. Если вы скомпилируете свою библиотеку (а не только для заголовка lib), вы вынуждаете не только тип интеллектуального указателя, но и конкретную версию, так как любые изменения в библиотеке интеллектуальных указателей нарушают совместимость вашего кода.

В качестве дополнительной заметки boost:: shared_ptr (boost 1.33+) в большинстве ситуаций thread safe, и он использует блокировку, свободной реализации на многих платформах. В любом случае, это должно дать вам представление о том, что вы должны учитывать.

Наконец, вы должны учитывать, что вы не только привязываете пользователя к использованию своего типа умного указателя, но и той же его версии. Если вы компилируете свой lib против определенной версии boost, пользователь привязан к этой конкретной реализации o

Ответ 9

введение boost:: shared_ptr заставляет вашего клиента использовать boost. для некоторых людей это незначительная проблема.

он также заставляет ваших клиентов использовать тот же самый компилятор, что и ваш lib, если ваша библиотека распространяется как скомпилированный двоичный файл. или, если ваша библиотека распределена в исходном коде, клиенты должны придерживаться собственного выбора компилятора, используемого для компиляции вашей библиотеки. это не является незначительной проблемой для любого проекта значительного размера.

Ответ 10

Используйте auto_ptr или придерживайтесь интерфейса C. Форсирование С++ libs в ваш интерфейс всегда уродливое, убивает любую возможность быть кросс-платформой и вызывает кошмар обслуживания для клиентов с различными "нисходящими" конфигурациями.

Как только С++ 0x станет основным для ваших клиентов, переключитесь на std::shared_ptr.