2011-01-01 3 views
4

я увидел следующий код,C++ - Есть ли неявный приведение от Fred * к auto_ptr <Fred>?

#include <new> 
#include <memory> 
using namespace std; 

class Fred; // Forward declaration 
typedef auto_ptr<Fred> FredPtr; 

class Fred { 
public: 
    static FredPtr create(int i) 
    { 
    return new Fred(i); // Is there an implicit casting here? If not, how can we return 
         // a Fred* with return value as FredPtr? 
    } 
private: 
    Fred(int i=10)  : i_(i) { } 
    Fred(const Fred& x) : i_(x.i_) { } 
    int i_; 
}; 

Пожалуйста, смотрите вопрос, указанный в функции создания.

Спасибо

// обновляется на основе комментариев

Да, код не может передать ошибку C2664 VC8.0 : «зЬй :: auto_ptr < _Ty> :: auto_ptr (Std :: auto_ptr < _Ty> &) бросок()»: не удается преобразовать параметр 1 из 'Fred *' до 'станд :: auto_ptr < _Ty> &'

код был скопирован с C++ FAQ 12.15.

Однако после внесения следующих изменений,

replace 
    return new Fred(i); 
with 
    return auto_ptr<Fred>(new Fred(i)); 

Этот код может передать VC8.0 компилятор. Но я не уверен, правильно ли это исправление.

+1

Скомпилировал ли этот код? Или вы просто это видели? –

+0

Оригинальное сообщение не имеет. – q0987

+0

Это правильное решение. Да. –

ответ

6

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

Этот код не компилируется.

+3

Неявное преобразование в 'auto_ptr' было бы безумным, учитывая семантику собственности' auto_ptr' – CodesInChaos

+0

Я просто проверял, чтобы сразу после публикации моего предыдущего ответа, также не компилируется для меня. Спасибо – Kos

+0

@ToAll, исходный код в книге не передает компилятор VS8.0 - спасибо – q0987

3

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

void MyFunction(const std::auto_ptr<Fred>& myFred) { 
    /* ... do something to Fred. */ 
} 

int main() { 
    Fred* f = new Fred; 
    MyFunction(f); // Not legal, but assume it is. 
    f->doSomething(); 
} 

Здесь, если вы могли бы передать сырой указатель на Фреда в MyFunction, а затем, когда эта функция вернула и временный объект auto_ptr был очищен, память вы выделенные в основной () будет восстановлен, и вызов f-> doSomething(), вероятно, вызовет segfault. Создание явного конструктора auto_ptr является защитой от этого; вы не хотите случайно приобретать эксклюзивную собственность на ресурс, когда кто-то другой считает, что у них уже есть такой доступ.

0

Фиксированная версия кода (return std::auto_ptr<Fred>(new Fred())) верна и действительна C++. Однако я не уверен, что функция create() покупает вас в том, что создание std::auto_ptr<T> должно быть в пределах набора навыков любого программиста на C++. Аналогичным образом, я не совсем понимаю, что typedef ing std::auto_ptr<Fred> до FredPtr покупает вас, за исключением необходимости искать то, что действительно есть FredPtr.