CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Dec 2016
    Posts
    9

    [RESOLVED] lazy initialisation with shared pointer

    Hi

    I am trying to introduce a lazy initialisation using a shared pointer.
    The function that performs the initialisation is a public member function and uses a lambda.

    I am unsure if the lambda is correct though. A compile error is generated on the code (below).

    A small subset of the code looks something like this:

    Code:
    #include <iostream>
    #include <memory>
    #include <string>
    #include <mutex>
    
    class Member;
    
    using sharep = std::shared_ptr<Member>;
    
    class Member {
      private:
        std::string sname;
        int sage{0};
        std::once_flag once_flag;
    
      public:
        Member(const std::string & name, int age) :  sname{name}, sage{age}  { }
        Member() {}
    
        Member ( const Member & ) = delete; // avoid copy
    
    
        ~Member() {}
        void init_profile(const std::string & name, const int age) {
          sname = name;
        }
    
        const std::string view_profile() const {
          return "Name : " + sname + ", age: " + std::to_string(sage) ;
        }
    
        void init(sharep & sptr, const std::string & name, const int age ) {
          std::call_once(once_flag, [](sharep & sptr){ if(!sptr) { sptr.reset(new Member);} } );
          sptr->init_profile(name, age);
        }
    };
    
    int main() {
      sharep sptr;
      sptr.init(sptr, "Harry Potter", 12);
      std::cout << "Profile : " << sptr->view_profile() << "\n";
    
      return 0;
    }
    The compile error generated is on line 40:
    Code:
    error: ‘using sharep = class std::shared_ptr<Member> {aka class std::shared_ptr<Member>}’ has no member named ‘init’
    Can anybody suggest where the code needs fixing?

    Thanks

  2. #2
    Join Date
    Dec 2016
    Posts
    9

    Re: lazy initialisation with shared pointer

    quick, update, I'm a bit further to a solution by modifying the code to the following:
    Code:
    #include <iostream>
    #include <memory>
    #include <string>
    #include <mutex>
    
    class Member;
    using sharep = std::shared_ptr<Member>;
    
    class Member {
      private:
        std::string sname;
        int sage{0};
        std::once_flag once_flag; // std::once_flag cannot be copied or moved
    
      public:
        Member(const std::string & name, int age) :  sname{name}, sage{age}  { }
        Member() {}
        Member ( const Member & ) = delete; // avoid copy
        ~Member() {}
    
        void init_profile(const std::string & name, const int age) {
          sname = name;  sage = age;
        }
    
        const std::string view_profile() const {
          return "Name : " + sname + ", age: " + std::to_string(sage);
        }
    
        void init(sharep & sptr, const std::string & name, const int age ) {
          std::call_once(once_flag, [/*sharep*/ & sptr](){ if(!sptr) sptr.reset(new Member); } ) ;
          sptr->init_profile(name, age);
        }
    };
    
    int main() {
      sharep sptr;
      sptr->init(sptr, "Harry Potter", 12);
      std::cout << "Profile : " << sptr->view_profile() << "\n";
      return 0;
    }
    But now a segmentation fault occurs instead. Any suggestions as to what the reason is?

  3. #3
    Join Date
    Dec 2016
    Posts
    9

    Re: lazy initialisation with shared pointer

    final solution.
    Code:
    #include <iostream>
    #include <memory>
    #include <string>
    #include <mutex>
    
    class Member;
    using sharep = std::shared_ptr<Member>;
    
    class Member {
      private:
        std::string sname;
        int sage{0};
        std::once_flag once_flag; // std::once_flag cannot be copied or moved
    
      public:
        Member(const std::string & name, int age) :  sname{name}, sage{age}  { }
        Member() {}
        Member ( const Member & ) = delete; // avoid copy
        ~Member() {}
    
        void init_profile(const std::string & name, const int age) {
          sname = name;  sage = age;
        }
    
        const std::string view_profile() const {
          return "Name : " + sname + ", age: " + std::to_string(sage);
        }
    
        void init(sharep & sptr, const std::string & name, const int age ) {
          std::call_once(once_flag, [/*sharep*/ & sptr](){ if(!sptr) sptr.reset(new Member); } ) ;
          sptr->init_profile(name, age);
        }
    };
    
    int main() {
      sharep sptr(new Member());
      sptr->init(sptr, "Harry Potter", 12);
      std::cout << "Profile : " << sptr->view_profile() << "\n";
      return 0;
    }
    How can I mark a thread as SOLVED ?

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: lazy initialisation with shared pointer

    final solution.
    Great that you managed to get it to work!

    How can I mark a thread as SOLVED ?
    From menu Thread Tools, use Mark Thread Resolved.

    [Done]
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: [RESOLVED] lazy initialisation with shared pointer

    Code:
    sharep sptr(new Member());
    Doesn't this rather mitigate against the initialisation using a shared pointer as sptr is initialised here?

    Consider
    Code:
    #include <iostream>
    #include <memory>
    #include <string>
    #include <mutex>
    
    class Member;
    using sharep = std::shared_ptr<Member>;
    std::once_flag member_flag; // std::once_flag cannot be copied or moved
    
    class Member {
    private:
    	std::string sname;
    	int sage{ 0 };
    
    public:
    	Member(const std::string & name, int age) : sname{ name }, sage{ age } { }
    	Member() {}
    	Member(const Member &) = delete; // avoid copy
    
    	void init_profile(const std::string & name, const int age) {
    		sname = name;  sage = age;
    	}
    
    	const std::string view_profile() const {
    		return "Name : " + sname + ", age: " + std::to_string(sage);
    	}
    
    	void init(sharep& sptr, const std::string & name, const int age) {
    		std::call_once(member_flag, [&]() {sptr.reset(new Member); });
    		sptr->init_profile(name, age);
    	}
    };
    
    int main() {
    	sharep sptr;
    
    	sptr->init(sptr, "Harry Potter", 12);
    	std::cout << "Profile : " << sptr->view_profile() << "\n";
    
    	sptr->init(sptr, "James Bond", 37);
    	std::cout << "Profile : " << sptr->view_profile() << "\n";
    	return 0;
    }
    where sptr isn't first initialised but is initialised once when init is first called which I think is what you were trying to achieve?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured