константа shared_ptr в shared_ptr

Как можно преобразовать shared_ptr, указывающий на константный объект, в shared_ptr, указывающий на неконстантный объект. Я пытаюсь сделать следующее:

boost::shared_ptr<const A> Ckk(new A(4));

boost::shared_ptr<A> kk=const_cast< boost::shared_ptr<A> > Ckk;

Но это не работает.


person user152508    schedule 16.12.2009    source источник


Ответы (4)


'boost::const_pointer_cast' сделает то, о чем вы просите, но обязательная вторая половина ответа заключается в том, что вам, вероятно, не следует его использовать. В 99% случаев, когда кажется, что вам нужно отбросить свойство const переменной, это означает, что у вас есть недостаток дизайна. Const иногда больше, чем просто показуха, и его отбрасывание может привести к неожиданным ошибкам.

Не зная более подробной информации о вашей ситуации, нельзя сказать наверняка. Но никакое обсуждение const-cast не будет полным без упоминания этого факта.

person Alan    schedule 16.12.2009
comment
Использование const_pointer_cast не является недостатком дизайна гораздо чаще, чем вы думаете. Например, стандартные контейнеры могут работать только с типами, конвертируемыми в тип содержащихся в них элементов. Таким образом, следующее невозможно, хотя логически правильно: vector<shared_ptr<T>> cont; shared_ptr<const T> a; cont.push_back(a); - person ; 02.06.2011
comment
@jons34yp: В этом нет ничего логически правильного. Вам дали указатель const; это означает, что вам не разрешено использовать его непостоянным образом. Если у вас есть список неконстантных указателей, и вы хотите поместить в него константный указатель, сложно. Приводя его к константе, вы нарушаете контракт с человеком, который дал вам этот указатель (этот контракт заключается в том, что вы не должны его менять). Это так же верно для обычных указателей, как и для shared_ptr. - person Nicol Bolas; 15.07.2011
comment
const_pointer_cast может быть полезен, если вы расширяете поведение общего указателя. Но вам, вероятно, следует делать это только в том случае, если вы относитесь к тому типу людей, которые действительно могут внести свой вклад в повышение. - person Brent; 15.10.2012
comment
@Brent расширение поведения общего указателя, что вы имеете в виду? - person curiousguy; 05.04.2017

используйте boost::const_pointer_cast, документацию.

person Nikola Smiljanić    schedule 16.12.2009

правильный путь должен быть таким

boost::shared_ptr<A> kk (boost::const_pointer_cast<A>(Ckk));
person YeenFei    schedule 16.12.2009

std::const_cast_pointer создает второй управляемый указатель. После приведения у вас есть доступный для записи указатель и исходный константный указатель. Пуансон остается прежним. Счетчик ссылок увеличен на 1.

Обратите внимание, что const_cast — это встроенное ключевое слово, а const_pointer_cast — это шаблонная функция в пространстве имен std.

Затем указатель с возможностью записи можно использовать для изменения значения из-под shared_ptr<const T>. ИМХО, указатель на запись должен временно сохраняться в стеке; в противном случае должен быть конструктивный недостаток.

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

#include <memory>
#include <iostream>
#include <cassert>

using namespace std;

typedef shared_ptr<int> int_ptr;
typedef shared_ptr<const int> const_int_ptr;

int main(void)
{
    const_int_ptr Ckk(new int(1));

    assert(Ckk.use_count() == 1);
    cout << "Ckk = " << *Ckk << endl;

    int_ptr kk = const_pointer_cast<int>(Ckk); // obtain a 2nd reference
    *kk = 2;                   // change value under the const pointer

    assert(Ckk.use_count() == 2);
    cout << "Ckk = " << *Ckk << endl;      // prints 3
}

В UNIX или Windows/Cygwin компилируйте с помощью

g++ -std=c++0x -lm const_pointer_cast.cpp
person Andreas Spindler    schedule 07.09.2011
comment
печатает 3 - откуда взялась 3? Это опечатка? - person Ben Hymers; 20.10.2011