Jul 9, 2017 at 6:16pm UTC
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.
A small subset of the code looks something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#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(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 is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
lazy_init_thread_safe02.cpp: In member function ‘void Member::init(sharep&, const string&, int )’:
lazy_init_thread_safe02.cpp:33:34: error: capture of non-variable ‘using sharep = class std::shared_ptr<Member>’
std::call_once(once_flag, [sharep & sptr](){ if (!sptr) sptr.reset(new Member); } )
^~~~~~
lazy_init_thread_safe02.cpp:8:39: note: ‘using sharep = class std::shared_ptr<Member>’ declared here
using sharep = std::shared_ptr<Member>;
^
lazy_init_thread_safe02.cpp:33:41: error: expected ‘,’ before ‘&’ token
std::call_once(once_flag, [sharep & sptr](){ if (!sptr) sptr.reset(new Member); } )
^
lazy_init_thread_safe02.cpp:34:7: error: expected ‘;’ before ‘sptr’
sptr->init_profile(name, age);
^~~~
lazy_init_thread_safe02.cpp: In function ‘int main()’:
lazy_init_thread_safe02.cpp:41:8: error: ‘using sharep = class std::shared_ptr<Member> {aka class std::shared_ptr<Member>}’ has no member named ‘init’
sptr.init(sptr, "Harry Potter" , 12);
^~~~
Compilation failed.
Could anybody suggest where the code needs modification ?
Last edited on Jul 9, 2017 at 6:16pm UTC
Jul 9, 2017 at 8:11pm UTC
Again,
sptr->init(sptr, "Harry Potter" , 12);
Will cause UB because sptr
is empty.
Last edited on Jul 9, 2017 at 8:12pm UTC
Jul 9, 2017 at 8:21pm UTC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#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()); // you missed this line
sptr->init(sptr, "Harry Potter" , 12);
std::cout << "Profile : " << sptr->view_profile() << "\n" ;
return 0;
}
Last edited on Jul 9, 2017 at 8:22pm UTC
Jul 9, 2017 at 8:48pm UTC
Hi blongho,
many thanks. I'm only a beginner C++ coder, but slowly making my way through C++ Concurrency in Action by Anthony Williams.
The above code is simply a test case I've created in order to try out some of his discussion on pages 60-63.
Jul 9, 2017 at 9:36pm UTC
one small change,
I modified line 36, from this:
sharep sptr(new Member());
to this:
sharep sptr = std::make_shared<Member>();
Jul 10, 2017 at 11:12am UTC
so no lazy initialization then.