I'm using a library which returns a reference to me.
I need to use this reference as class-attribute.
Not being able to initialize the attribute in constructor directly (the lib needs to be inited before), I thought about using a shared_ptr for lazy initialization:
#include <iostream>
#include <string>
#include <tr1/memory>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo() :
testString_( std::tr1::shared_ptr< std::string& >() )
{
//do some initialization of the library here...
//now init the shared_ptr
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
std::tr1::shared_ptr< std::string& > testString_;
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
But unfortunately this does not work. g++ gives messages like this:
error: forming pointer to reference type ‘std::string&’
I tried some other ways to get the reference into the shared_ptr, but nothing works... Perhaps you could give me a hint.
Note:
- In "real-world" instead of std::string the datatype is a class without default constructor.
- For those who still wonder: The above is just a simplified example-code :)
UPDATE:
- While trying to apply the suggestions, I found out that contrary to the used std::string from example, my class has a private copy constructor. This means I'm not able to just copy the object into a new one.
If you are provided by a reference only, that means that you are not responsible for memory management, and that in turns means that you cannot use your own memory management. That is, you should not use any type of smart pointer to hold that object.
While you can obtain the address of the real object with the & operator, doing so will cause undefined behavior later on when your shared_ptr goes out of scope and tries to free the memory and the library itself tries to free the memory on it's own.
You simply cannot take the address of a reference.
You can however use shared_ptr<string> and initialize it with &getStringReference. But that will cause the shared_ptr to try to delete the string, causing it to fail since it was never allocated using new. To fix this, make a copy:
testString_.reset(new std::string(getStringReference()))
Even better, let your class just store the reference directly. The you don't need to bother about memory management at all:
class Foo
{
std::string& _testString;
// ...
}
You need to understand the semantics of references and of memory management.
What you probably want is a raw pointer in your class. I assume you can't use a reference because you do not know what object it will refer to until you make the function call so you want to do something like ref=getRef();
You have no way of automatically "protecting" your pointer against becoming "dangling", but do not think there is anything you can do to rectify this situation. You just have to look at the documentation as to how to use the reference/pointer properly.
You could consider using Boost.Optional, which support optional references. This way, you could lazy initialize your reference without taking ownership of the referenced object as you do by using shared_ptr:
#include <iostream>
#include <string>
#include <boost/optional.hpp>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo()
{
//do some initialization of the library here...
//now init the optional reference
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
boost::optional< std::string& > testString_; //<-- note the use of optional
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
Stop using shared_ptr now. Sharing is not an unilateral decision.
That being said, you are returned a reference to an object, not the object proper. There are two things you can do:
copy the object, and therefore deciding to manage the lifetime of the copy yourself
take a reference to the object, and let it up to the library you called to manage the lifetime, in which case you'll need to have some knowledge about it
I would definitely recommend copying unless there is a reason not to, much easier to get it right.
If you go for copying, use boost::optional<LibObject> within your class, this way you'll bypass the initialization issue.
If you wish to use a reference, you can still use boost::optional, and it'll work too! Use it as such: boost::optional<LibObject&>, but make sure the object you have a reference to will live long enough.
Finally, regarding the initialization issue, you could use a function to process the initialization and return a reference directly, thus initializing the reference of your class in the initialization list.
You can not use a shared_ptr with a reference type, because a reference is just that - a reference to an object. It is not a real object.
Next example is just simplified version of what you tried to do :
int main()
{
int &* a;
}
Use a factory function?
class Library
{
public:
static void Init();
static LibraryThing & getThing();
};
class Foo
{
public:
static shared_ptr<Foo> Create()
{
if (!_libInit)
{
Library::Init();
_libInit = true;
}
return make_shared(new Foo(Library::getThing()));
}
private:
Foo(LibraryThing & ref) : _ref(ref)
{
}
private:
LibraryThing & _ref;
static bool _libInit;
};
Related
I have defined a class that holds a reference to a list of static functions which are defined
outside of the class. These functions each take a pointer to that particular instance of the class as a argument.
I'm passing the this pointer to the functions. But that doesn't seem right to me.
Is there a better way?
The code below is a simplified version:
#include <iostream>
#include <map>
class A
{
public:
typedef void (*action_func)(A*);
typedef std::map<int, action_func> func_map;
A(func_map the_map)
:m_map(the_map)
{}
void execute_action(int action_id)
{
auto it = m_map.find(action_id);
if(it != m_map.end())
{
auto cmd = it->second;
cmd(this);
}
}
private:
func_map& m_map;
};
static void function_1(A* ptrToA)
{
std::cout << "This is function_1\n";
}
static void function_2(A* ptrToA)
{
std::cout << "This is function_2\n";
}
static func_map functions =
{
{1, function_1},
{2, function_2}
};
int main()
{
A obj(functions);
obj.execute_action(1);
obj.execute_action(2);
return 0;
}
The output of the above is this:
This is function_1
This is function_2
When storing references and pointers to things outside the class it is important to reason about their lifetimes. Generally, the thing being referenced should outlive the thing that references it.
In your particular case, static func_map functions; has static storage duration, that is it is created before main() starts and is destroyed after main() ends.
So you can safely use it inside A obj, which lives within the scope of main():
int main()
{
A obj(functions);
. . .
}
However, the constructor of A isn't just storing it - it stores a reference to its temporary copy instead:
A(func_map the_map)
:m_map(the_map)
{}
func_map& m_map;
What's worse, the temporary copy lives only until the end of the full-expression, i.e. until the end of A obj(functions);. So if you use it after that you will be accessing a dangling reference (undefined behavior).
To fix that, change it to a pass by-reference:
A(func_map& the_map)
:m_map(the_map)
{}
func_map& m_map;
Now there's no issue.
I'm passing the this pointer to the functions. But that doesn't seem right to me.
The same lifetime reasoning applies - if the thing where you pass this into doesn't use it for longer than this is alive, then technically there is no issue. In your case the function calls are synchronous, so by definition this is alive during each function call.
Whether or not it's "right" from a design perspective is impossible to say from the provided example. There could be better solutions, but there are also design patterns (e.g. Strategy Pattern) that are based on passing a reference to self around. So in the end it's a design choice.
Base abstract class:
class Satellite
{
public:
Satellite();
virtual void center()=0;
virtual ~Satellite(){}
};
First derived class
class Comm_sat:public Satellite
{
public:
Comm_sat();
void center() override{cout << "comm satellite override\n";}
};
Second derived class
class Space_station:public Satellite
{
public:
Space_station();
void center() override{cout << "space station override\n";}
};
Pointer version of the functions
void f(Satellite* ms){
ms->center();
delete ms;
}
int main()
{
Comm_sat* cs = new Comm_sat;
Space_station* ss = new Space_station;
f(cs);
f(ss);
}
The objects created using new in main() are properly destroyed in f(), right?
Reference version of the functions
void f(Satellite& ms){
ms.center();
}
int main()
{
Comm_sat cs;
Space_station ss;
f(cs);
f(ss);
}
Is the reference version better?
Besides, I try to use unique_ptr, however, I get errors
void f(Satellite* ms){
ms->center();
}
int main()
{
unique_ptr<Comm_sat> cs{new Comm_sat};
unique_ptr<Space_station> ss{new Space_station};
f(cs);
f(ss);
}
Error: cannot convert std::unique_ptr<Comm_sat> to Satellite* for argument 1 to void f(Satellite*)
Error: type class std::unique_ptr<Comm_sat> argument given to delete, expected pointer delete cs;
Same error for the other derived class.
Is the reference version better?
Yes, although a better way to put this would be "the pointer version is worse". The problem with the pointer version is that you pass it a valid pointer, and get a dangling pointer when the function returns. This is not intuitive, and leads to maintenance headaches when someone modifies your code thinking that you have forgotten to delete cs and ss in the main, not realizing that f deletes its argument.
The version that uses a reference is much better in this respect, because the resources are managed automatically for you. Readers of your code do not need to track the place where the memory of cs and ss gets released, because the allocation and release happen automatically.
I try to use unique_ptr, however, I get errors
There is no implicit conversion from std::unique_ptr<T> to T*. You need to call get() if you want to pass a raw pointer:
f(cs.get());
f(ss.get());
The objects created using new in main() are properly destroyed in f(), right?
They're destroyed, and cleaned up correctly, yes. "Properly" is a stretch though, since all this manual-new-and-delete-raw-pointers stuff is poor style.
The reason unique_ptr isn't working for you is that ... it's a unique_ptr, not a raw pointer. You can't just pass it as a raw pointer.
Try
void f(Satellite* ms){
ms->center();
}
// ...
f(cs.get());
or better, unless you really need to pass nullptr sometimes,
void f(Satellite& ms){
ms.center();
}
// ...
f(*cs);
or best of all, since you don't show any reason to require dynamic allocation at all:
void f(Satellite& ms);
// ...
{
Comm_sat cs;
f(cs);
} // no new, no delete, cs goes out of scope here
I am new to C++11. In fact until recently, I programmed only using dynamic allocation, in a way similar to Java, e.g.
void some_function(A *a){
a->changeInternalState();
}
A *a = new A();
some_function(a);
delete a;
// example 2
some_function( new A() ); // suppose there is **no** memory leak.
Now I want to reproduce similar code with C++11, but without pointers.
I need to be able to pass newly created class class A directly to function useA(). There seems to be a problem if I want to do so with non-const normal reference and It works if I do it with rvalue reference.
Here is the code:
#include <stdio.h>
class A{
public:
void print(){
++p; // e.g. change internal state
printf("%d\n", p);
}
int p;
};
// normal reference
void useA(A & x){
x.print();
}
// rvalue reference
void useA(A && x){
useA(x);
}
int main(int argc, char** argv)
{
useA( A{45} ); // <--- newly created class
A b{20};
useA(b);
return 0;
}
It compiles and executes correctly, but I am not sure, if this is the correct acceptable way to do the work?
Are there some best practices for this kind of operations?
Normally you would not design the code so that a temporary object gets modified. Then you would write your print function as:
void useA(A const & x){
x.print();
}
and declare A::print as const. This binds to both rvalues and lvalues. You can use mutable for class member variables which might change value but without the object logically changing state.
Another plan is to keep just A &, but write:
{ A temp{45}; useA(temp); }
If you really do want to modify a temporary object, you can write the pair of lvalue and rvalue overloads as you have done in your question. I believe this is acceptable practice for that case.
The best thing about C++11 move semantics is that most of the time, you get them "for free" without having to explicitly add any &&s or std::move()s in your code. Usually, you only need to use these things explicitly if you're writing code that does manual memory management, such as the implementation of a smart pointer or a container class, where you would have had to write a custom destructor and copy constructor anyway.
In your example, A is just an int. For ints, a move is no different from a copy, because there's no opportunity for optimization even if the int happens to be a disposable temporary. Just provide a single useA() function that takes an ordinary reference. It'll have the same behavior.
I have some methods that take a reference to a given object, and some are taking boost::shared_ptr. So far in my test method I created a shared_ptr pointing to one of these objects and pass *ptr to the methods expecting a reference. Is it possible to do it the other way round, e.g. create a local object on the stack, and then create a shared pointer to it in a safe way, to arrive at the straightforward alternative to &obj operator with traditional pointers?
If you find you need this, something is probably horribly wrong with your code.
If the functions take a shared pointer, it should be because they need to extend the lifetime of the object. If they don't need to extend the lifetime of the object, they should take a reference.
With what you're doing, they can't extend the lifetime of the object. If they need to, and can't, they may wind up accessing an object that has gone out of scope through a copy of the shared pointer you passed them. Boom.
It's slightly possible this might make sense. It may be that they need to extend the lifespan but you will make sure that the object remains valid longer than the longest they might possibly need to extend it. But I'd still strongly suggest not doing this. It's incredibly fragile and makes all the code you call dependent on exactly how the calling code behaves.
#include <boost/shared_ptr.hpp>
void null_deleter(int *)
{}
int main()
{
int i = 0;
boost::shared_ptr<int> p(&i, &null_deleter);
}
You can pass an appropriate deleter in the constructor of the form:
template<class Y, class D> shared_ptr(Y * p, D d);
The deleter object must do nothing in its operator()(), such as the function:
template <typename T>
void no_op(T*) {}
with which you can then construct:
boost::shared_ptr<Foo> f(&obj, no_op<Foo>);
You can use c++11 lambda function:
boost::shared_ptr<Foo> f(&obj, \[ ](Foo*){});
You can pass null_deleter in the constructor.
#include <boost/shared_ptr.hpp>
#include <boost/core/null_deleter.hpp>
int main()
{
int a = 0;
boost::shared_ptr<int> pi(&a, boost::null_deleter());
}
But watch this case: using object after destruction:
#include <boost/shared_ptr.hpp>
#include <boost/core/null_deleter.hpp>
class Y
{
public:
void tryUse()
{
std::cout << "attempt to use :"<< (uintptr_t)(void*)this<< std::endl;
}
~Y()
{
std::cout << "destructor: "<< (uintptr_t)(void*)this<< std::endl;
}
};
struct Y_user
{
boost::shared_ptr<Y> p;
~Y_user()
{
std::cout << "Y_user destructor: "<< (uintptr_t)(void*)this<< std::endl;
if (p.get())
p->tryUse();
}
};
int main()
{
{
Y_user yu;
Y y;
boost::shared_ptr<Y> p (&y, boost::null_deleter() );
yu.p = p;
}
}
Will lead to console output like this:
destructor: 140737179995232
Y_user destructor: 140737179995264
attempt to use :140737179995232
I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};