Pergunta

Nós temos uma biblioteca C ++ que nós fornecemos para vários clientes diferentes. Recentemente, fez a mudança do uso de ponteiros crus na interface pública para usar boost :: sharedptr vez. Isso proporcionou um enorme benefício, como você pode imaginar, em que agora os clientes já não têm de se preocupar com quem necessita de apagar o que e quando. Quando fizemos o interruptor eu acreditava que era a coisa certa a fazer, mas isso me incomodou que tivemos que incluir algo a partir de uma biblioteca de terceiros em nossa interface pública - geralmente a evitar esse tipo de coisa, se puder. I racionalizado que esse impulso foi praticamente parte da linguagem C ++ agora, e nosso caso de uso requer que o código do cliente e os ponteiros preensão biblioteca para os objetos. No entanto, recentemente um de nossos clientes nos perguntou se poderíamos passar a usar uma classe ponteiro inteligente neutro na interface, porque a nossa biblioteca é essencialmente forçando-os a uma determinada versão de boost- um ponto que eu certamente compreender e apreciar. Então agora eu estou querendo saber qual é o melhor curso de ação poderia ser. Eu tenho pensado sobre isso um pouco, e se perguntou sobre a criação de uma classe ponteiro inteligente simples que simplesmente segurou um ponteiro inteligente verdadeiro impulso. Mas, em seguida, os clientes provavelmente imediatamente encher um daqueles em seu sabor de boost :: sharedptr, e em seguida seríamos três ponteiros compartilhados profundas - o que pode ser um problema, ou talvez não. De qualquer forma, eu adoraria ouvir algumas opiniões da comunidade sobre a melhor maneira de resolver este problema.

Edit: Eu originalmente disse transferência de propriedade, mas eu deveria ter especificado que o código em ambos os lados da fronteira necessidade API para manter um ponteiro para o objeto

.
Foi útil?

Solução

shared_ptr <> é parte da linguagem, como do lançamento de TR1. Veja: (TR1)

Outras dicas

Uma possível solução é enviar boost :: shared_ptr com o seu projeto. Como tudo o que consiste em cabeçalhos, isso iria libertar seus clientes de ter que instalar as bibliotecas de impulso manualmente. Você pode usar bcp para obter todos os arquivos necessários para uma especial biblioteca de impulso, incluindo o próprio bibliotecas. Eu fiz isso quando eu trabalhava para uma empresa naquela época e precisava boost::shared_ptr e ele realmente funcionou muito.

Se a semântica são realmente transferência de propriedade , por que não usar auto_ptr uma vez que é padrão C ++? Internamente, você ainda pode construir o seu shared_ptr do do auto_ptr e, em seguida, ter compartilhado propriedade se você precisar dele.

Em primeiro lugar, se você distribuir a sua biblioteca de código-fonte e não como uma biblioteca compilada, você pode ignorar esta resposta. Existem também alguns problemas janelas específicas que podem não ser relevantes para outras plataformas.

Eu, pessoalmente, acho que você deve evitar ter muito funk c ++ na interface pública de sua biblioteca uma vez que pode causar uma série de problemas no cliente.

Eu não sei como aplicável este é o seu exemplo particular, mas eu, pessoalmente, ter problemas onde os símbolos da biblioteca STL eu usei em conflito com os da biblioteca de terceiros quando eu atualizado para uma nova versão. Isto significava que temos acidentes em lugares estranhos e eu tive que fazer muitos truques para evitar o problema. No final eu fiquei com a versão antiga da biblioteca por causa disso.

Outro problema que você pode correr em é que compiladores diferente c ++ pode mangle os mesmos símbolos de forma diferente o que significa que potencialmente precisa fornecer uma biblioteca separada para cada compilador quiser apoiar, mesmo se eles usam a mesma versão Boost. Confira o livro "Imperfect C ++" para uma discussão sobre isso.

No mundo atual de diferentes compiladores e ambientes C ++ Eu acho que a triste verdade é que você deve evitar ter nada C em sua interface e certifique-se de ligar a sua biblioteca dinamicamente (a conflitos evitar ao ligando seus clientes vincula sua biblioteca, janelas biblioteca de tempo de execução pode ser uma verdadeira dor aqui). Você ainda pode usar impulso e tanto extravagante c ++ no interior de sua biblioteca que quiser desde que todos os seus símbolos serão isoladas a partir de seu ambiente de clientes na dll.

Se você realmente quer ter ponteiros inteligentes e outros agradável C ++ funcionalidade na interface de sua biblioteca, construir uma camada de conveniência que você distribuir o código fonte. Isso fará com que sempre compilado no ambiente de clientes. Esta interface em seguida, chama suas funções C expostas em formas inteligentes. Eu não acho que é uma boa idéia para aumentar o uso em que a camada seja, uma vez que irá forçar seus clientes a adotá-lo, mesmo se eles não querem, no entanto, é fácil substituí-lo ou encontrar outra solução, uma vez que a camada é distribuído como fonte código.

Outro recurso interessante é que é geralmente mais fácil de chamar funções C em uma dll de C ++ funções com desconfiguração do nome estranho se você deseja expor sua biblioteca para outros idiomas além do C / C ++.

Esta abordagem definitivamente faz a sua vida mais complicada, em muitos aspectos, mas é uma maneira de torná-lo menos provável que as pessoas evitem sua biblioteca porque ele simplesmente não era possível vincular com sucesso com seu próprio código.

Esta é C ++. Você sabe, você poderia template a classe de interface da execução ponteiro compartilhado.

Esta é uma pergunta interessante que tive há algum tempo. Você forçar seus usuários em qualquer biblioteca que você fornecer, ou deixá-los decidir sobre o que é melhor em seu projeto? Como sempre, a questão é o que você está oferecendo e que você está exigindo do usuário.

Se você usar ponteiros crus, você permite que todos os tipos de possibilidades. O código de usuário pode usar um ponteiro bruto, armazená-lo em std :: auto_ptr, shared_ptr (se o reforço ou TR1), ou sua versão caseira de um ponteiro inteligente. Mas isso também pode obter o usuário em apuros se esqueça de liberar a memória, e isso requer mais algum código em seu lado se quiser apenas um temporária criada por uma chamada de método (se você fornecer ponteiros crus, eles vão ter que armazenar o ponteiro em uma variável de ponteiro [possivelmente inteligente] non-temporária).

Agora, se você usar um ponteiro inteligente você está forçando a sua solução para o usuário. Se eles planejam usar sua própria versão de um ponteiro inteligente (digamos que você usar boost :: shared_ptr e eles querem std :: tr1 :: shared_ptr) já não estão autorizados a usá-lo se eles trabalham com a sua interface. Seja qual for o ponteiro inteligente que você decidir (além std :: auto_ptr que é especial) você não está apenas forçando uma solução, mas também os problemas que tem.

Se o usuário tem um aplicativo com vários segmentos, e sua solução não é thread-safe, o usuário é obrigado a uma solução inseguro. Se, por outro lado, o ponteiro inteligente é thread-safe, mas inccurs custos de bloqueio, esses custos são empurrados para os seus usuários, mesmo que eles trabalham em um aplicativo com vários segmentos. Se você compilar sua biblioteca (não um cabeçalho única lib), então você está forçando não só um tipo de ponteiro inteligente, mas também uma versão específica do mesmo, desde que as alterações na biblioteca ponteiro inteligente vai quebrar a compatibilidade do seu código.

Como uma nota lateral, boost :: shared_ptr (boost 1.33+) é fio segura na maioria das situações, e ele usa uma implementação livre-lock em muitas plataformas. De qualquer forma isso deve lhe dar uma idéia de coisas que você deve considerar.

Finalmente, você deve considerar que você não é apenas obrigatório o usuário a utilizar o seu tipo de ponteiro inteligente, mas também a mesma versão do mesmo. Se você compilar seu lib contra uma versão específica do impulso que o usuário é obrigado a que determinada aplicação o

Você pode usar o href="http://www.boost.org/doc/libs/1_37_0/tools/bcp/bcp.html" rel="nofollow noreferrer"> utilitário de cópia impulso

introdução boost :: shared_ptr força o seu cliente para uso impulso. para algumas pessoas, isso é uma questão menor.

também obriga os seus clientes para usar o mesmo compilador como usado pelo seu lib, se o seu lib é distribuído como binário compilado. ou, se a biblioteca é distribuído em código fonte, os clientes têm de manter a sua própria escolha do compilador usado para compilar seu lib. isso não é uma questão menor a qualquer projeto de tamanho considerável.

Use auto_ptr ou vara para uma interface C. Forçando libs C ++ em sua interface é sempre feio, mata qualquer chance de ser multiplataforma, e provoca um pesadelo de manutenção para clientes com diferentes configurações "a jusante".

Assim que C ++ 0x é mainstream o suficiente para os seus clientes, mude para std::shared_ptr.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top