2013-08-19 1 views
3

Почему ниже код компилироватьshared_ptr с = символ не имеет

shared_ptr<parent> p(new parent); 

в то время как ниже один не

shared_ptr<parent> p2 = new parent; 

Есть ли причина не позволяя «=» символ для shared_ptr?

Вообще, если указатель как

int *p = new int; 

должны быть такими же, как и

int *p(new int); 

не так ли?

+0

Возможный дубликат [Отсутствует уникальный \ _ptr и оператор друзей = перегрузка] (http://stackoverflow.com/questions/14916931/missing-unique-ptr-and-friends-operator-overload) – user1233963

ответ

4

std::shared_ptr «принимающий указатель» конструктор объявляется explicit.

template< class Y > 
explicit shared_ptr(Y* ptr); 

При том, что вы не можете использовать инициализацию копирования (shared_ptr<parent> p2 = new parent;).

Лучшая причина, по которой я могу думать, почему std::shared_ptr «s конструктор сделан explicit, что вы меньше шансов сделать ошибки прохождения сырой, неуправляемые по std::shared_ptr объекта к функции, получающей std::shared_ptr.

#include <memory> 


void func(std::shared_ptr<int> ptr) { /* ... */} 

int main() { 
    auto iptr = std::make_shared<int>(); 
    func(iptr); // OK 

    /* 
    int* iptr = new int; 
    func(iptr); // Unclear who would eventually manage (delete) the pointer 
    // ... 
    delete iptr; // Undefined behavior! 
    */ 
} 

Если конструктор не был сделан explicit, то вы могли бы сделать закомментированный код.

Кроме того, как то, что @R. Martinho Fernandes имеет suggested, у вас может возникнуть проблема, если передаются указатели не new.

int myint; 
int* iptr = &myint; 
func(iptr); // iptr doesn't point to a newed (dynamically-allocated) object 
      // std::shared_ptr, by default, uses delete on its managed pointer 
      // if there are no more references to that pointer 

Тем не менее вы можете сделать это не так, если вы не будете осторожны, когда вы используете два отдельных std::shared_ptr с для управления сырой указатель.

int* riptr = new int; 
std::shared_ptr<int> iptr(riptr); 
std::shared_ptr<int> iptr2(riptr); // WRONG! 

С вашими вопросами о сырых указателей, то две, по существу, то же самое, но это не обязательно относится к std::shared_ptr.

+1

Марк Гарсия: Спасибо для ответа. Я знал о явном конструкторе.Но, я хочу знать, почему это стало явным? Есть ли причина для этого? –

+0

@ Saran-san Пожалуйста, смотрите мое редактирование. –

+3

@Saran неправильный вопрос. Как правило, для проектирования API, когда у вас есть конструктор с одним аргументом, начинайте с явного и найдите причины, чтобы сделать его неявным, а не наоборот. Неявные преобразования часто вызывают проблемы и делают это тихо. –

3

Поскольку конструктор принимает указатель в качестве единственного аргумента явно, вы не можете использовать обозначения назначения здесь, потому что считается implicit conversion.

Вы также можете использовать удобную функцию make_shared() здесь:

std::shared_ptr<parent> p2 = std::make_shared<parent>(); 

Этот способ создания быстрее и безопаснее, поскольку он использует one вместо two allocations: один для объекта и один для общих данных, которые общий указатель использует для управления объектом.

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