2016-11-18 5 views
-1

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

С примера:

using Ptr = shared_ptr<int>; 

void switch_all(Ptr &p) { 
    p.reset(new int(14)); 
} 

int main() { 
    Ptr a(new int(12)); 
    Ptr b = a; 
    Ptr c(a); 

    cout << "Initial situation: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *b.get() << '\t' << b.get() << endl; 
    cout << *c.get() << '\t' << c.get() << endl; 

    switch_all(c); 

    cout << "After reset: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *b.get() << '\t' << b.get() << endl; 
    cout << *c.get() << '\t' << c.get() << endl; 
} 

Это выводит

Initial situation: 
12  0xb8797038 
12  0xb8797038 
12  0xb8797038 
After reset: 
12  0xb8797038 
12  0xb8797038 
14  0xb8797468 

То, что я хочу сделать, это изменить switch_all таким образом, что выход становится

Initial situation: 
12  0xb8797038 
12  0xb8797038 
12  0xb8797038 
After reset: 
14  0xb8797468 
14  0xb8797468 
14  0xb8797468 

Возможно ли это? Как?

ответ

1

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

Что вы просите требуется дополнительный уровень косвенности, например:

using UPtr = unique_ptr<int>; 

void switch_all(UPtr &p) { 
    p.reset(new int(14)); 
} 

int main() { 
    UPtr a(new int(12)); 
    UPtr &b = a; 
    UPtr &c = a; 

    cout << "Initial situation: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *b.get() << '\t' << b.get() << endl; 
    cout << *c.get() << '\t' << c.get() << endl; 

    switch_all(c); 

    cout << "After reset: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *b.get() << '\t' << b.get() << endl; 
    cout << *c.get() << '\t' << c.get() << endl; 
} 

Или

using UPtr = unique_ptr<int>; 

void switch_all(UPtr *p) { 
    p->reset(new int(14)); 
} 

int main() { 
    UPtr a(new int(12)); 
    UPtr *b = &a; 
    UPtr *c = &a; 

    cout << "Initial situation: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *(b->get()) << '\t' << b->get() << endl; 
    cout << *(c->get()) << '\t' << c->get() << endl; 

    switch_all(c); 

    cout << "After reset: " << endl; 
    cout << *a.get() << '\t' << a.get() << endl; 
    cout << *(b->get()) << '\t' << b->get() << endl; 
    cout << *(c->get()) << '\t' << c->get() << endl; 
} 
+0

Я надеялся, что есть способ, чтобы изменить указатель, сохраненный с помощью объекта менеджера, так что все общие указатели, указывающие на этот объект-менеджер, теперь указывают на другой управляемый объект. Полагаю, мне придется создавать класс shared_ptr с нуля. – user6245072

 Смежные вопросы

  • Нет связанных вопросов^_^