Hi i am reading C++ primer 5th addition and have some doubts in the section of weak_ptr. It is written that
By using a weak_ptr, we don’t affect the lifetime of the vector to which a given StrBlob points. However, we can prevent the user from attempting to access a vector that no longer exists.
Then they have given the following code as an example:
#include<iostream> #include<string> #include<vector> #include<memory> #include<initializer_list> using namespace std; class StrBlobPtr; class StrBlob { friend class StrBlobPtr; public: typedef std::vector<std::string>::size_type size_type; StrBlob():data(std::make_shared<std::vector<std::string>>()){ } StrBlob(std::initializer_list<std::string> il):data(make_shared<vector<std::string>>(il)){ } size_type size() const { return data->size(); } bool empty() const { return data->empty(); } void push_back(const std::string &t){ data->push_back(t); } std::string& front(){ check(0,"front on empty StrBlob"); return data->front(); } std::string& front() const{ check(0,"front on const empty StrBlob"); return data->front(); } std::string& back(){ check(0,"back on empty StrBlob"); return data->back(); } std::string& back() const { check(0,"back on const empty StrBlob"); return data->back(); } void pop_back(){ check(0,"pop_back on empty StrBlob"); data->pop_back(); } private: std::shared_ptr<std::vector<std::string>> data; void check(size_type i, const std::string &msg) const{ if(i >= data->size()){ throw out_of_range(msg); } } StrBlobPtr begin(); StrBlobPtr end(); }; class StrBlobPtr { public: typedef std::vector<std::string>::size_type size_type; StrBlobPtr():curr(0){ } StrBlobPtr(StrBlob &a, size_type sz = 0):wptr(a.data), curr(sz){ } std::string& deref() const { auto p = check(curr, "dereference past end"); return (*p)[curr]; } StrBlobPtr& incr(){ check(curr, "increment past end of StrBlobPtr"); ++curr; return *this; } std::shared_ptr<std::vector<std::string>> check(std::size_t i, const std::string &msg) const{ auto ret = wptr.lock(); if(!ret){ throw std::runtime_error("unbound StrBlobPtr"); } if(i>= ret->size()){ throw std::out_of_range(msg); } return ret; } private: std::weak_ptr<std::vector<std::string>> wptr; size_type curr; }; StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } StrBlobPtr StrBlob::end() { auto ret = StrBlobPtr(*this, data->size()); } int main(){ return 0; } My questions are as follows:
- How can we prevent the user from attempting to access a vector that no longer exists? I can't come up with a use case,how can we use the above quoted statement in this example?
- How does this example shows/verifies that we can prevent the user from attempting to access a vector that no longer exists? *If this example does not shows what they have written then why is this example there in the book?*Note that i have written if.
auto ret = wptr.lock()?auto ret = wptr.lock()and i understand what is happening in this statement. Here we are checking if there are any shared_ptr pointing to the same memory to which wptr points and depending upon the result we get a nullptr or a share_ptr.retis tested to see if the shared_ptr has already released the objectif(!ret){Note that the control block persists until all shared and weak pointers have been destroyed.main()function is empty. So the program does exactly nothing. In other words yes, it's a very bad example. Maybe this will help?dereffunction certainly won't stop the vector from going away before the string is manipulated via that potentially dangling reference.