I have a piece of code that requires passing a function object (functional). I can't use function pointers because I need to store some state variables. Let's say I have quite a few state variables. Is it ok to pass the function object by reference? I've only seen function objects passed by value. This is what my code will look like:
struct FunctionObject {
double a, b, x, y;
double operator() (int v, int w) {....}
};
template <class T>
Class MyClass {
T& func;
.....
public:
MyClass(T& func):func(func) {}
.....
};
Passing function objects by reference is fine, but you should be aware that many C++ algorithms copy function objects, so if you need a library algorithm to respect your state you should pass it as a reference inside your function object:
struct State {
double a, b, x, y;
};
struct Function {
State &state;
explicit Function(State &state): state(state) {}
double operator() (int v, int w) {....}
};
State state;
std::...(..., Function(state), ...)
Also, some library algorithms (e.g. transform) require pre-C++11 that the function object have no side effects i.e. no state whatsoever; this requirement is rarely enforced and is relaxed in C++11.
It depends mainly on how you intend to instanciate FunctionObject (how you create function objects). If you use references, you must ensure the function object outlives the user (MyClass) object.
For instance:
MyClass* createObject() {
MyFunction f(...); // function object created
return new MyClass(f); // reference used
// function object destroyed => reference invalid
}
is incorrect because the returned object has a reference on a destroyed (invalid) function.
Since you gain very little by passing by reference (avoid copying a small object), it's not worth the hassle (checking objects lifetime) and the risk an oversight (bug)
The synthax is correct but...
most of the time you're going to call the function object later in your code, so you need to make sure that the reference you've provided in MyClass is still in the scope
so in the end since you need to keep the function object in the heap rahter than the stack, you'll have to create a pointer to it... so I recommend using a pointer...
Function objects are objects. You can pass them by reference and you can store references to them, subject to the usual lifetime issues. However, the algorithms in std:: are allowed to make copies of their function objects whenever they like, so any stored state may well be stale, so it may be better to write your function object as a wrapper around a pointer or reference to its state.
Related
Are smart pointers considered as pointers? And thus can they implicitly used as pointers?
Let's say I have the following class:
class MyClass {
//...
std::shared_ptr<AnotherClass> foo() { /*whatever*/ };
void bar(AnotherClass* a) { /*whatever too*/ };
//...
}
Then can I use MyClass the following way?
// m is an instance of MyClass
m.bar(m.foo());
No they can't be used interchangable. You would get a compiler error in your example. But you can always get the raw pointer by shared_ptr::get().
NO! It would be a terrible API. Yes, you could easily implement it within shared_ptr, but just because you could doesn't mean you should.
Why is it such a bad idea? The plain-pointer-based interface of bar doesn't retain an instance of the shared pointer. If bar happens to store the raw pointer somewhere and then exit, there's nothing that guarantees that the pointer it had stored won't become dangling in the future. The only way to guarantee that would be to retain an instance of the shared pointer, not the raw pointer (that's the whole point of shared_ptr!).
It gets worse: the following code is undefined behavior if foo() returns a pointer instance that had only one reference when foo() returned (e.g. if foo is a simple factory of new objects):
AnotherClass *ptr = m.foo().get();
// The shared_ptr instance returned by foo() is destroyed at this point
m.bar(ptr); // undefined behavior: ptr is likely a dangling pointer here
Here are the options; consider those listed earlier first before considering their successors.
If bar(AnotherClass *) is an external API, then you need to wrap it in a safe way, i.e. the code that would have called Original::bar should be calling MyWrapped::bar, and the wrapper should do whatever lifetime management is necessary. Suppose that there is startUsing(AnotherClass *) and finishUsing(AnotherClass *), and the code expects the pointer to remain valid between startUsing and finishUsing. Your wrapper would be:
class WithUsing {
std::unique_ptr<AnotherClass> owner; /* or shared_ptr if the ownership is shared */
std::shared_ptr<User> user;
public:
WithUsing(std::unique_ptr<AnotherClass> owner, std::Shared_ptr<User> user) :
owner(std::move(owner)), user(std::move(user)) {
user.startUsing(owner.get());
}
void bar() const {
user.bar(owner.get());
}
~WithUsing() {
user.finishUsing(owner.get());
}
};
You would then use WithUsing as a handle to the User object, and any uses would be done through that handle, ensuring the existence of the object.
If AnotherClass is copyable and is very cheap to copy (e.g. it consists of a pointer or two), then pass it by value:
void bar(AnotherClass)
If the implementation of bar doesn't need to change the value, it can be defined to take a const-value (the declaration can be without the const as it doesn't matter there):
void bar(const AnotherClass a) { ... }
If bar doesn't store a pointer, then don't pass it a pointer: pass a const reference by default, or a non-const reference if necessary.
void bar(const AnotherClass &a);
void bar_modifies(AnotherClass &a);
If it makes sense to invoke bar with "no object" (a.k.a. "null"), then:
If passing AnotherClass by value is OK, then use std::optional:
void bar(std::optional<AnotherClass> a);
Otherwise, if AnotherClass takes ownership, passing unique_ptr works fine since it can be null.
Otherwise, passing shared_ptr works fine since it can be null.
If foo() creates a new object (vs. returning an object that exists already), it should be returning unique_ptr anyway, not a shared_ptr. Factory functions should be returning unique pointers: that's idiomatic C++. Doing otherwise is confusing, since returning a shared_ptr is meant to express existing shared ownership.
std::unique_ptr<AnotherClass> foo();
If bar should take ownership of the value, then it should be accepting a unique pointer - that's the idiom for "I'm taking over managing the lifetime of that object":
void bar(std::unique_ptr<const AnotherClass> a);
void bar_modifies(std::unique_ptr<AnotherClass> a);
If bar should retain shared ownership, then it should be taking shared_ptr, and you will be immediately converting the unique_ptr returned from foo() to a shared one:
struct MyClass {
std::unique_ptr<AnotherClass> foo();
void bar(std::shared_ptr<const AnotherClass> a);
void bar_modifies(std::shared_ptr<AnotherClass> a);
};
void test() {
MyClass m;
std::shared_ptr<AnotherClass> p{foo()};
m.bar(p);
}
shared_ptr(const Type) and shared_ptr(Type) will share the ownership,
they provide a constant view and a modifiable view of the object, respectively. shared_ptr<Foo> is also convertible to shared_ptr<const Foo> (but not the other way round, you'd use const_pointer_cast for that (with caution). You should always default to accessing objects as constants, and only working with non-constant types when there's an explicit need for it.
If a method doesn't modify something, make it self-document that fact by having it accept a reference/pointer to const something instead.
Smart pointers are used to make sure that an object is deleted if it is no longer used (referenced).
Smart pointer are there to manage lifetime of the pointer they own/share.
You can think of a wrapper that has a pointer inside. So the answer is no. However you can access to the pointer they own via get() method.
Please note that it is not so difficult to make dangling pointers if you use get method, so if you use it be extra cautious.
Can I pass a unique_ptr's reference to a function? If not why should I avoid it?
Ex:
void func(unique_ptr<Clss>& ref);
main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
fn(a);
}
Can I pass a unique_ptr's reference to a function?
Yes, a unique_ptr is class like any other.
You should do this when you want to mutate an existing unique_ptr from a function (e.g. calling .reset() on it).
If only you want to access the object inside unique_ptr<T>, take T& or const T& in your function interfaces, so that they can be used independently of unique_ptr.
According to Herb Sutter:
https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
Passing unique_ptr by reference is for in/out unique_ptr parameters.
void f( unique_ptr<widget>& ); // (d)
This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.
Thanks #sgvd
See this code snippet, two ways of passing unique_ptr as function parameter. fun1 will take ownership of the object ( hence should be forwarded from the caller) but func2 commits thats the reference unique_ptr object will be passed as reference and will not be modified by the function.
void func1(unique_ptr<Clss>&& moved_obj) // this function takes ownership
{
//do something with the moved_obj
moved_obj.reset();
}
void func2(const unique_ptr<Clss>& ref_obj) // this function takes reference
{
unique_ptr<Clss> new_obj = std::make_unique<Clss>(*(ref_obj));
}
int main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
func1(std::move(a));
unique_ptr<Clss> b = std::make_unique<Clss>();
func2(b);
return 0;
}
I see those valid meaningful signatures:
void take_ownership(std::unique_ptr<Clss>);
// or void take_ownership(std::unique_ptr<Clss>&&);
void use(/*const*/ Clss*);
// or void use(/*const*/ Clss&);
std::unique_ptr<Clss> create(/*args..*/);
void might_take_ownership(std::unique_ptr<Clss>&);
The later might make sense, but it is more difficult to reason with (as any I/O argument).
If you can, prefer one of the other.
Passing a std::unique_ptr to a function is perfectly fine as long as you respect the same rules you would when passing a regular reference to a function:
the underlying std::unique_ptr and the object it points to must live at least as long as the function will use the reference;
in case of multi-threading, barriers must be put in place.
I would like to ask a question about methods' const-correctness. Let me illustrate the situation.
class MyClass
{
public:
...
void DiscussedMethod() { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
I have a class MyClass which keeps a pointer to OtherClass. In DiscussedMethod it calls OtherClass::NonConstMethod which modifies some visible data.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)? Would it be a bad practice? Or is both fine?
What if the OtherClass kept a pointer to the MyClass and in NonConstMethod modified some of the MyClass' data (meaning that the MyClass member data would change during the DiscussedMethod call). Would it be a bad practice to make the DiscussedMethod const then?
As far as I've been able to find out, the const on a method is mostly a code documenting thing, so I would probably lean toward to not making the DiscussedMethod const, but I would like to hear your opinions.
EDIT: Some replies take the into account whether the object pointed to by otherClass is owned by the MyClass object. This is not the case in the scenario I'm working with. Lets say that both objects exist independently side by side (with the ability to modify each other). I think this analogy describes my situation quite well.
For example consider something like doubly-linked list, where each element is a class that keeps pointer to its neighbours and member variable color. And it has method MakeNeighboursRed which changes the color of its neighbours but doesn't affect the calling object's state itself. Should I consider making this method const?
And what if there was some possibility that MakeNeighboursRed would call neighbour's MakeNeighboursRed. So in the end the state of the object for which MakeNeighboursRed has been called originally would change as well.
And I would like to thank you all for your opinions :-)
If MyClass owns the OtherClass instance i wouldn't make DiscussedMethod constant.
The same goes for classes, managing resources. I.e. the standard containers do not return non const references or pointers to the managed memory using const functions, although it would be "possible" (since the actual pointer holding the resource is not modified).
Consider
class MyClass
{
public:
bool a() const { return otherClass->SomeMethod(); }
void b() const { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
void foo (MyClass const &x)
{
cout << boolalpha << x.a() << endl;
x.b(); // possible if b is a const function
cout << boolalpha << x.a() << endl;
}
The foo could print two different values although an implementor of foo would probably expect that two function calls on a const object will have the same behaviour.
For clarification:
The following is invalid according to the standard since the const version of operator[] returns std::vector<T>::const_reference which is a constant reference to the value type.
std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a
It would be possible if there was only one signature of this function, namely referece operator[] (size_t i) const;, since the operation does not alter the internal pointers of the vector but the memory they point to.
But the memory, managed by the vector is considered to be part of the vectors state and thus modification is impossible through the const vector interface.
If the vector contains pointers, those pointer will still be unmodifiable through the public const vector interface, although the pointers stored in the vector may well be non const and it may well be possible to alter the memory they point to.
std::vector<int*> const b = { /* ... */ };
int x(2);
b[0] = &x; // impossible, b is const
*b[0] = x; // possible since value_type is int* not int const *
In OOP object should be fully described by its state, available through its interface. Thus, const methods should not alter object's state, if these changes might be observed through the interface.
A good example is a mutable mutex inside your class to guard some shared resources. It might be modified from const method, since it does not introduce any changes observable via class interface.
General rule of thumb is, that if you can make a member function const, you probably should. The reason for that is that it allows you to catch unintended behaviour and bug easier.
Another argument in favor would be that if you have this function as const you are allowed to call it on const object, so it isn't really a documentation thing.
Overall it depends what the other class is. It's not black and white...
If otherClass is a log object (for example) and you want to log the operation of the current object then it's perfectly fine calling it from a const function.
If the otherClass is a container that for design (or implementation) purposes is implemented as a separate object than effectively a const function modifies the object making this a very bad idea.
I hope this helps.
It's totaly incorrect to make DiscussedMethod const as it changes it's *this state. The only loophole to this is making non-logically-part-of-object's-state member data mutable so they can be changed in const functions. This would be things like a member that hold a count for "number of times function x() has been called". Any thing else is part of the object's state, and if a function changes it (at any level), that function isn't const.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)?
otherClass is member data, and it (or rather, the object it points to) gets modified.
Consider the semantics should the pointer to otherClass be refactored to a fully-owned object... whether something is held as a pointer, reference, or object doesn't change the semantical ownership, IMO.
This question already has answers here:
What is a reference variable in C++?
(12 answers)
Closed 8 years ago.
Facts that I have known:
There are three types of variables in C++: variables, pointers and references.
Variables is kinda label for the memory that stores the actual data.
Pointers stored the address of the variables.
References are alias for the variables.
My questions:
By observation, the use of variables names and references is exchangeable. Is that true?
What is the difference between passing a variable name as parameter and passing a reference? e.g.,
void func(int a); vs void func2(int& b);
Thanks a million!
Here is a way to understand the difference:
Objects that can change state are also called "variables".
Pointers are objects (variable or not). They have a state.
References are "nicknames". They don't have a state, but expose the state of the refereed object (which is why you can't re-assign a reference, it's not an actual object).
Now, in some cases references might be implemented as pointers, but from the language point of view, references are just not pointers, they really are additional names for an object already existing.
As pointers are objects, and have a state, passing pointers to functions will copy that state, the pointer's state, not the pointee's state. However, references have no state, so if you pass a reference to a function, it's the refereed object that you pass (by copy).
By observation, the use of variables names and references is
exchangeable. Is that true?
"References are nickname" is the best way to understand references.
What is the difference between passing a variable name as parameter
and passing a reference? e.g.,
void func(int a); vs void func2(int& b);
The first implementation ask for a copy of the object passed. That is, internally func() can do anything to a, without changing the object that was passed to func() because internally func() made a copy of that object and manipulates the copy, not the original.
The second implementation ask for "a nickname for an object already existing". First, the object have to exist and if passed, a nickname for it will be created inside the function. That nickname, the reference b, is still a nickname for the original object. This mean that any manipulation done to b will affect the original object passed to func2().
func() signature says "I need this data but I will not modify the original object passed.".
func2() signature says "I need an object that I WILL certainly modify, pass it so that I can modify it".
Bonus stage:
At this point, if you don't know yet about const, that might be useful: in function signatures const is used with references to specify the arguments that are "read-only".
Let me clarify:
void func3( const int& b);
Here func3 says: "I need to access to an object, but really I will not make a copy of it. However I guarantee that I will not change that object".
So, why would we need that? Because some objects are expensive to copy. int is cheap to copy so most people will just pass it and func() and func3() are basically equivalent (depends on implementation but generally true).
If however we want to pass, says, a very big object, like a data buffer, we really don't want to copy it again and again just to apply some algorithms.
So we do want to pass it by reference. However, depending on the function, sometime you want to extract information and work with it, so you only need "read-only" access to the argument. In this case you use const Object&. However, if you need to apply the algorithm to the object passed, you need to be able to modify it, which you could call "write-access". In this case, you need to use a normal reference.
Asking for a copy basically mean that you want to manipulate an object that is the same state than the passed object, but is not the passed object.
To summarize:
func( T object ) : I want to have a copy of an object of type T;
func( T& object ) : I want to have "write-access" to an object of type T - assume that I will modify that object!;
func( const T& object ) or func( T const & object ) // which are the same : I want to read the state of an object, but I guarantee you that I will not modify it, I want "read-only" access.
Actually, the "read-only" guarantee could be violated using const_cast<> but that's a different story and it's only used in some very very very narrow cases.
Last thing you need to know is that if you have a member function, then you can do:
class K{
public:
void func() const; // see the const?
};
In this specific case, what you say is that inside the function, which is basically equivalent to:
void func( const K* this );
In this case you can see that this is a pointer but it's pointing to a const object. This mean that func() guarantee that the object it is member of (this) is never modified through this function (except some specific cases, see mutable keyword, another long story).
Let's say you have these two functions:
void addone(int a) {
a += 1;
}
void addone_bis(int &a) {
a += 1;
}
If you call the first function in your main function, the value will only change in the function addone and not in the main, whereas if you call addone_bis the value of a will also be changed in the main function.
int main() {
int test_a = 10;
int test_b = 11;
addone(test_a);
// test_a still equals 10.
addone_bis(test_b);
// test_b now equals 12.
}
Did I correctly answer to your question?
Your first example is what is known as PASSING BY VALUE. What this means is that a copy of the ACTUAL value is passed into the routine.
When passing in the way of your second example, this is what is known as PASSING BY REFERENCE. A reference is ESSENTIALLY a passing of the variable into the routine such that its ACTUAL VALUE can be modified by the called routine without DE-REFERENCING.
Given the following code:
class foo;
foo* instance = NULL;
class foo
{
public:
explicit foo(int j)
: i(j)
{
instance = this;
}
void inc()
{
++i;
}
private:
int i;
};
Is the following using defined behavior?
const foo f(0);
int main()
{
instance->inc();
}
I'm asking because I'm using a class registry, and as I don't directly modify f it would be nice to make it const, but then later on f is modified indirectly by the registry.
EDIT: By defined behavior I mean: Is the object placed into some special memory location which can only be written to once? Read-only memory is out of the question, at least until constexpr of C++1x. Constant primitive types for instance, are (often) placed into read-only memory, and doing a const_cast on it may result in undefined behavior, for instance:
int main()
{
const int i = 42;
const_cast<int&>(i) = 0; // UB
}
Yes, it is undefined behavior, as per 7.1.5.1/4:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
Note that object's lifetime begins when the constructor call has completed (3.8/1).
This may be one of the rare cases where the not very known mutable keyword could be used:
mutable int i;
i can now be changed even if the object is const. It's used when logically the object doesn't change, but in reality it does.
For example:
class SomeClass
{
// ....
void DoSomething() { mMutex.lock(); ...; }
mutable Mutex mMutex;
}
In DoSomething() the object doesn't logically change and yet mMutex has to change in order to lock it. So it makes sense to make it mutable, otherwise no instance of SomeClass could be const (assuming you lock the muetx for every operation).
If you define a const instance of the object, then cast away the const-ness, and modify the contents of the object, you get undefined behavior.
From the sound of things, what you want is exactly the opposite: create a non-const instance of the object, then return a const pointer to that object to (most of) the clients, while the "owner" retains a non-const pointer to the object so it can modify members as it sees fit.
You'd typically manage a situation like this by defining the class with a private ctor, so most clients can't create objects of the type. The class will then declare the owner class as a friend, so it can use the private ctor and/or a static member function to create instances (or often only one instance) of the object. The owner class then passes out pointers (or references) to const objects for clients to use. You need neither a mutable member nor to cast away constness, because the owner, which has the "right" to modify the object, always has a non-const pointer (or, again, reference) to the object. Its clients receive only const pointers/references, preventing modification.
Calling a non-const (by declaration) member function on a const object is not illegal per se. You can use whatever method you wish to work around the compiler restrictions: either an explicit const_cast or a trick with constructor as in your example.
However, the behavior is only defined as long as the member function you are calling does not make an attempt to actually physically modify the object (i.e. modify a non-mutable member of the constant object). Once it makes an attempt to perform a modification, the behavior becomes undefined. In your case, method inc modifies the object, meaning that in your example the behavior is undefined.
Just calling the method, again, is perfectly legal.
It's hard to tell the intent with these arbitrary names. If i is intended as just a use counter, and it isn't really considered part of the data, then it is perfectly appropriate to declare it as mutable int i; Then the const-ness of an instance is not violated when i is modified. On the other hand, if i is meaningful data in the space being modeled, then that would be a very bad thing to do.
Separately from that, though, your example is a bit of a mess for what you seem to be asking. foo* instance = NULL; is effectively (if confusingly) using a NULL as a numeric zero and initializing instance, which is not const; then you separately initialize f, which is const, but never reference it.
Under GCC, at least, your constructor should be explicit foo(int j) with the word int.
However, it's perfectly fine to have two pointers to the same value, one const and the other not.
Why dont you make use of const cast ?
Any reason to make object as const eventhough its state is not constant?
Also make following change :
explicit foo(int j = 0) : i(j)
{ instance = this; }