2015-06-08 5 views
1

Вот мой код.Как получить доступ к содержимому std :: shared_ptr?

std::shared_ptr<WSUStudent> WSUStudent::registerStudent(
    std::string lastName, 
    std::string firstName 
) 
{ 
    auto result = std::shared_ptr<WSUStudent>(new WSUStudent(lastName, firstName)); 

    s_allStudents.insert(&result); 

    return result; 
} 

Мне удалось изменить функцию, чтобы она возвращала shared_ptr вместо обычного указателя. Я успешно инкапсулировал «новый» оператор с общим указателем в соответствии с назначением (я думаю), но строка кода ниже «auto» не работала без &, и она не работает с &. Я получаю сообщение об ошибке, что нет соответствующего вызова функции, с или без &. Эта строка кода пытается вставить нового ученика (или указателя на нового ученика?) В список всех учеников. Однако метод «insert» не локально переопределен, поэтому я не совсем уверен, что делать здесь. Ошибка печати ниже.

/mnt/hgfs/Data Structures and Algorithms/HW04/WSUStudent.cpp:146:32: error: no matching function for call to ‘std::set<WSUStudent*>::insert(std::shared_ptr<WSUStudent>*)’ 
    s_allStudents.insert(&result); 

Суть этого задания является исправление утечек памяти («новые» заявления, которые не удаляются с их указателями), поворачивая обычные указатели на слабые указатели и общие указатели. Исходный код выглядит следующим образом.

WSUStudent *WSUStudent::registerStudent(
    std::string lastName, 
    std::string firstName 
) 
{ 
    auto result = new WSUStudent(lastName, firstName); 

    s_allStudents.insert(result); 

    return result; 
} 

Я собираюсь сделать это неправильно? Я не могу запустить строку s_allStudents.

+0

какого типа 's_allStudents'? –

+1

Объявление для s_allStudents является статическим std :: set s_allStudents; Я собираюсь попробовать изменить WSUStudent * в скобках на shared_ptr, пока я жду. – user3424549

+0

's_allStudents.insert (& result);' нехорошо. Вы храните указатель на объект в стеке. –

ответ

3

Учитывая тип s_allStudents, вы можете использовать:

s_allStudents.insert(result.get()); 

Однако лучшим вариантом будет изменить тип s_allStudents.

static std::set<std::shared_ptr<WSUStudent>> s_allStudents; 

и использование:

s_allStudents.insert(result); 

Update

по умолчанию operator<() из shared_ptr такова, что объекты в s_allStudents будут отсортированы по значению указателя. Если вы хотите отсортировать объекты с использованием другого критерия, вам необходимо определить пользовательский функтор/функцию в качестве параметра шаблона.

struct MyCompare 
{ 
    bool operator<(shared_ptr<WSUStudent> const& lhs, 
        shared_ptr<WSUStudent> const& rhs) const 
    { 
     // Implement the logic ... 
    } 
}; 

и использовать его как:

static std::set<std::shared_ptr<WSUStudent>, MyCompare> s_allStudents; 
+3

Вы не имеете в виду 'std :: set >'? – sjdowling

+0

OP сказал, что назначение должно было возвратить 'std :: shared_ptr' из функции. Если 's_allStudents' предназначен для * владельца * объектов (и это выглядит наиболее вероятно), то добавление * raw указателя * в один из контейнеров-обладателей является опасным. Также, если вы храните объекты по значению, как в своем втором примере, и возвращаете 'std :: shared_ptr', указывая на них, снова это UB ждет. – Galik

+0

@sjdowling, да. Спасибо, что дали мне знать. –

1

Если вы собираетесь вернуть std::shared_ptr<WSUStudent> тогда вы возвращаете собственности права на объект, который вы создали - значит кто-то будет пытаться удалить его в какой-то момент.

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

Я предполагаю, что, как вы используете этот класс, но то, что я имею в виду идет что-то вроде этого:

class WSUStudent 
{ 
    // you really need to store shared pointers in here 
    static std::set<std::shared_ptr<WSUStudent>> s_allStudents; 

    std::string lastName; 
    std::string firstName; 

    // only the static factory function can make students 
    WSUStudent(
     const std::string& lastName, // passing by const& is more usual (idiomatic) 
     const std::string& firstName) 
    : lastName(lastName) 
    , firstName(firstName) 
    { 
    } 

public: 

    static std::shared_ptr<WSUStudent> registerStudent(
     const std::string& lastName, 
     const std::string& firstName); 
}; 

std::shared_ptr<WSUStudent> WSUStudent::registerStudent(
    const std::string& lastName, 
    const std::string& firstName 
) 
{ 
    auto result = std::shared_ptr<WSUStudent>(new WSUStudent(lastName, firstName)); 

    // put the shared student in your set 
    s_allStudents.insert(result); 

    return result; 
} 

// define your set 
std::set<std::shared_ptr<WSUStudent>> WSUStudent::s_allStudents; 

int main() 
{ 
    // make students 
    auto s = WSUStudent::registerStudent("bill", "bob"); 
    // all deletions should be in order 
} 
Смежные вопросы