I thought I can't assign a constant shared_ptr
to a non-constant shared_ptr
. But surprisingly I am able to assign as below and it is working fine.
#include <iostream>
#include <memory>
using namespace std;
int main()
{
const std::shared_ptr<const string> a = std::make_shared<const string>("Hello world");
std::shared_ptr<const string> b = a;
cout << "a count " << a.use_count() << ", b count " << b.use_count() << endl;
return 0;
}
.use_count()
is getting printed as 2. Can any one please help me to understand how I am able to do it?
The situation in your code is exactly the same as here:
const int a = 5;
int b = a;
std::cout << "a=" << a ", b=" << b << std::endl; // a=5, b=5
b = 10;
std::cout << "a=" << a ", b=" << b << std::endl; //a=5, b=10
Not particularly surprising, right? I had const int
, and I used it to initialize non-const int
. The value from a
got copied into b
and a
wasn't modified at all.
Same occurs with const std::shared_ptr
. Copy-constructing another object is not modifying the original object.
use_count
can be changed, because it's not a member of std::shared_ptr
class. std::shared_ptr
requires two memory blocks allocated on the heap - a control block and actual object block.
Every std::shared_ptr
instance only stores a pointer to the control block and to the actual object. The control block stores use count (number of std::shared_ptr
s that hold the pointer to it).
When you copy std::shared_ptr
, it increments the use count in control block and gets the same two pointers. When std::shared_ptr
dies, it decrements use count (and deletes both blocks if use count reaches 0).
So, to sum up: use count is not a member of std::shared_ptr
, and as such it can change even for const std::shared_ptr
(otherwise const std::shared_ptr
would be quite useless).
The string
that a
and b
are pointing at is still const
in both cases, but the pointer b
isn't, so you could change what b
is pointing at:
std::shared_ptr<const string> b = a;
b = std::make_shared<const string>("New string");
But you can't change what a
is pointing at (since a
is const
):
a = std::make_shared<const string>("Won't compile");
Similarly:
const char* const a = "Hello world";
const char* b = a;
const char* c = "Something else";
b = c; // the pointer "b" is not const and can be changed
// a = c; // won't compile since the pointer "a" itself is const
Let's simplify:
#include <iostream>
#include <memory>
int main() {
const auto a = std::make_shared<const std::string>("Hello world");
auto b = a;
std::cout << "a count " << a.use_count() << ", b count " << b.use_count() << "\n";
}
Types allowing copy-construction from a mutable object, but not from a constant one, are very rare and all user-defined. Mostly, they pre-date move-semantics, and thus C++11.
std::shared_ptr
, introduced with C++11, is not such an exception. Why should it?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.