С++ 11 сохранение нескольких общих указателей в качестве исходных указателей

Мой вопрос касается shared_ptr и make_shared в С++ 11. У меня два вектора, первый хранит интеллектуальные указатели, а второй хранит исходные указатели. Первый вектор работает так, как я это сделал, но vector2 просто запутывает...

Пример кода

#include <iostream>
#include <vector>
#include <memory>

int main() {
    std::vector<std::shared_ptr<int>> vector1;
    vector1.push_back(std::make_shared<int>(1));
    vector1.push_back(std::make_shared<int>(2));
    vector1.push_back(std::make_shared<int>(3));

    std::vector<int*> vector2;
    vector2.push_back(std::make_shared<int>(4).get());
    vector2.push_back(std::make_shared<int>(5).get());
    vector2.push_back(std::make_shared<int>(6).get());

    std::cout << "vector1 values:" << std::endl;
    for(auto &value: vector1) { std::cout << *value << std::endl; }

    std::cout << "vector2 values:" << std::endl;
    for(auto &value: vector2) { std::cout << *value << std::endl; }

    return 0;
}


Выход

vector1 values:
1
2
3
vector2 values:
6
6
6


Вопрос

Я понимаю, что было бы намного проще создавать исходные указатели для начала и не пытаться преобразовывать интеллектуальные указатели, но мне было любопытно узнать почему это происходит? Также почему каждое нажатие меняет все значения в vector2?


Ссылки

Вот несколько вопросов, которые я нашел в stackoverflow, но они не ответили на мой вопрос или, может быть, я не понял ответы...

Ответы

Ответ 1

Причина, по которой вы будете использовать shared_ptr, - это то, что вы хотите, чтобы память, на которую указывает, была освобождена, когда все экземпляры, указывающие на нее, выходят за рамки. shared_ptr уничтожается сразу после вызова .get() на нем, поэтому у вас сразу есть висячий указатель. Результатом операции разыменования является undefined, что означает, что оно может или не может вернуть значение, которое имеет смысл, или может даже сделать что-то совершенно не связанное (например, сбой).

Это функция. Вы хотите, чтобы это произошло: в противном случае вы будете пропускать память. Представьте себе этот код:

vector<int> integers;
integers.push_back(*make_shared<int>(6).get());

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

Ответ 2

Вы видите поведение undefined. Когда вы это сделаете:

vector2.push_back(std::make_shared<int>(4).get());

Создается временный shared_ptr и копируется указатель на его управляемый объект в vector. Это немедленно становится висящим указателем.