Почему счетчик shared_ptr увеличивается при передаче в качестве константной ссылки на базовый класс? - PullRequest
3 голосов
/ 28 июня 2019

Почему счетчик shared_ptr<drived> увеличивается, когда я передаю его функции, которая ожидает const shared_ptr<base>&?

В этот вопрос один из ответов упоминает:

shared_ptr<Base> and shared_ptr<Derived> are not covariant

Я подозреваю, что это относится к моему вопросу. Что это значит, что они не являются ковариантными?

Вот фрагмент кода для демонстрации сценария:

#include <iostream>
#include <memory>

class Base {};

class Derived : public Base {};

void f(const std::shared_ptr<Base>& x)
{
    std::cout << "in function expecting const shared_ptr<Base>& - Use count: " << x.use_count() << std::endl;
}

int main(int argc, char const *argv[])
{
    std::cout << "Base class" << std::endl;
    auto a = std::make_shared<Base>();
    std::cout << "Created shared_ptr:  Initial use count: " << a.use_count() << std::endl;
    f(a);

    std::cout << "------------------\nChild class" << std::endl;
    auto b = std::make_shared<Derived>();
    std::cout << "Created shared_ptr. Initial use count: " << b.use_count() << std::endl;
    f(b);

    return 0;
}

Результаты:

>> g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Base class
Created shared_ptr:  Initial use count: 1
in function expecting const shared_ptr<Base>& - Use count: 1
------------------
Child class
Created shared_ptr. Initial use count: 1
in function expecting const shared_ptr<Base>& - Use count: 2

1 Ответ

7 голосов
/ 28 июня 2019

A shared_ptr<Derived> не является shared_ptr<Base>. Они совершенно разных типов.

Чтобы получить shared_ptr<Base> из shared_ptr<Derived>, вам нужно его создать. Компилятор может вызывать конструктор , потому что он не помечен как явный. Это увеличит количество пользователей, потому что они разделяют права собственности.

template< class Y > shared_ptr( const shared_ptr<Y>& r ) noexcept;

Создает shared_ptr, который разделяет владение объектом, управляемым r. Если r не управляет объектом, *this также не управляет объектом. Перегрузка шаблона не участвует в разрешении перегрузки, если Y* неявно не конвертируется в (до C ++ 17), совместимую с (начиная с C ++ 17) T*.

Вы можете убедиться, что создан новый shared_ptr, изменив f() на неконстантную ссылку. Компилятор должен выдать вам ошибку, потому что вы не можете привязать временную ссылку к неконстантной ссылке. Смотрите здесь

...