Is use count on `const std::shared_ptr<...>' mutable? - c++

I'm trying to adapt some pre-existing code to make use of std::shared_ptr<...>. It is a `message passing system' so the basic context is:
Public Method:
void writeReport(std::shared_ptr<const ReportBase> pReport) {
/* This is a public method for writing a report. I might do
additional stuff in here but end by forwarding to the
private method. */
writeReport_(pReport);
}
Private Method:
void writeReport_(std::shared_ptr<const ReportBase> pReport) {
if( certain conditions )
processReport_(pReport);
writeBytes_(serialize(pReport));
}
Processing Method:
void processReport_(std::shared_ptr<const ReportBase> pReport) {
processReportImpl(pReport);
if( certain other conditions )
reportDeque_.push_back(pReport);
}
Of the above pseudo-code, for example, processReport_(...) might be the only method which, under certain conditions, would want to actually store the record. The other methods are simply interested in the contents of the object pointed to. So, were it not for the need to sometimes copy the shared_ptr in processReport_(...) (i.e., 'store' the record), I would simply pass const ReportBase * to all my nested functions and avoid the overhead of pass-by-value (i.e., use count increments).
So, I want to pass std::shared_ptr<const ReportBase>& (and maybe && where appropriate) but want to preclude some rogue nested method from actually modifying what the pointer points to. So I think I want to pass const std::shared_ptr<const ReportBase>& to prevent that...
... but, again, in processReport_(...) I'll sometimes want to make a copy to store the record.
Which finally leads me to the question(s)...
is use count on a std::shared_ptr mutable?
Why can (or can't) I do a copy assignment on a const std::shared_ptr<...> to a std::shared_ptr<...>?
Does the const make the entire control block of the shared_ptr const? Or does the leading const only apply to the raw pointer value?
And if someone wants to answer tangentially 'don't worry so much about passing by value into nested functions' or 'I have a completely different approach for you' then I'd be interested to hear that too.

std::shared_ptr stores a pointer to the control block, which is allocated on the heap. After all, it has to be shared across all copies of that shared_ptr. So, when you apply a const to your std::shared_ptr, you are merely making that pointer const. The control block object being pointed to remains non-const. Think ControlBlock* const. Therefore, there is no need for an explicit mutable keyword there, although logically, the control block is indeed mutable.

If I understand your question correctly I would use a function like this
void processReport(const std::shared_ptr<ReportBase> &report) {
if( certain other condition ) {
reportDeque_.push_back(report); // will make the copy here
}
With the const std::shared_ptr<ReportBase> & you don't increment the use count, so if you add it to the vector it will have to be a copy of the shared_prt and therefore increase the count, if not the count stays the same.

Related

C++ When does it make sense to pass a const struct parameter by value vs. reference?

I've seen a similar question to this, but i'd like some clarification...
Assuming a basic C++ class:
class MyClass
{
public:
struct SomeData
{
std::wstring name;
std::vector<int> someValues;
};
void DoSomething(const SomeData data);
}
I understand that data will be passed as const to DoSomething and that is ok since data will not be modified in any way by the function...but I am used to seeing & specified with const parameters to ensure that they are passed by reference, e.g.
void DoSomething(const SomeData& data);
That seems more efficient to me. If we omit the &, then isn't data being passed by value to DoSomething? I'm not sure why it would ever be preferable to pass a const parameter by value when you can pass by reference and avoid the copy occurring?
Pass by value/reference and const-correctness are two different concepts. But used together.
Pass by Value
void DoSomething (SomeData data);
Pass by value is used when it is less costly to copy and do not want to keep references to foreign objects. This function could (if it is inside a class) keep a pointer to this in some case and have its own copy.
Pass by reference
void DoSomething (SomeData& data);
Always use pass by reference if you know this might cause a performance loss copying the struct. This function could (if it is inside a class) keep a pointer to this in some case and pointing to a foreign object. Keeping pointers to foreign objects mean you should aware of its life-time and when this foreign object goes out of bound. More importantly changes to foreign object appears to your pointer.
const correctness
void DoSomething (const SomeData data); // const for local copy
void DoSomething (const SomeData& data); // const for callers object
Adding constto pass by value or reference means this function does not change it. But not having or having & decides which object you are trying to add safety of modifying. const is a very helpful tool in C++ in terms of Documenting APIs, provide compile time safety, allow more compiler optimizations.
Read this article.
The biggest problem with void DoSomething(const SomeData data) is that it conflates interface and implementation. From the caller's point of view, the const doesn't change anything; the function receives a copy anyway, and the original object is not modified. What the implementation does or does not with its own, function-internal copy should not bother the caller and should thus not be expressed in the interface.
The const does make the implementation more const-correct if the copy is not changed, but leaking implementation details into the interface is a high price to pay. I recommend not using void DoSomething(const SomeData data).
As always, performance gains or losses should not be overestimated here. It's more about semantics and conventions.
Passing a const value is mostly informational for the caller, it shows intent. This is important to make code easy to read, understand and maintain.
It might also be possible for the compiler to add some extra optimizations if it knows that the function doesn't modify its argument. For example it might cause the compiler to not perform a copy at all.
This:
void DoSomething(const SomeData data);
is a bit unusual, because while it does not change anything for the caller (who can pass a const or non-const value), it restricts what the function can do internally. There's not a lot of value in that, and it's not commonly done.
Passing by reference (const or not) is more efficient if the value is expensive to copy, including if it is larger than approximately two pointers on the target platform. In other words, if SomeData were a struct containing two integers it would probably be more efficient to pass it by value. But if it contains a std::map or some larger data, better pass it by reference.
An exception to this is if the function is going to copy the value anyway, then it is better to take it by value, because the value might be "moved" instead of copied if the caller allows it.

'mutable' variable mutable only by one of the const methods?

today I have learned about the mutable keyword in C++ and would like to use it in my code.
I have a class with many const methods and one of them should be able to modify some of the object's variables (conserving the logical state of the object). However I don't want to let all the const methods to modify the variable, only the selected one. Is there any way of doing that? Maybe with const_cast?
(The code I am talking about is an implementation of the Union-Find structure. The Find operation does not change the logical state of the structure (it only searches for a root of a tree), but changes the physical state by doing so-called path compression)
Thanks!
EDIT: I have added an excerpt from the code I am referring to:
class UnionFind {
public:
void Union(int a, int b) {...}
int Find(int x) const {
// logically, this method is const
while(x != parents[x]) {
// path compression
// the next three lines modify parents and sizes,
// but the logical state of the object is not changed
sizes[parents[x]] -= sizes[x];
sizes[parents[parents[x]]] += sizes[x];
parents[x] = parents[parents[x]];
x = parents[x];
}
return x;
}
int someOtherMethodThatAccessesParents() const {
// this method does access parents, but read only.
// I would prefer if parents behaved like if it was
// not 'mutable' inside this method
...
}
private:
// these have to be mutable if I want the Find method
// to be marked const (as it should be)
// but making them mutable then does not enforce
// the physical non-mutability in other const methods :(
mutable std::vector<int> parents;
mutable std::vector<int> sizes;
};
On first glance this can't be achieved unless you use a nasty const_cast. But don't do that since the behaviour on attempting to modify a variable following a const_cast that was originally declared as const is undefined.
However, it might be feasible to achieve what you want using friendship since that can be controlled on a function by function basis whereas mutability, as you correctly point out, cannot be.
Put the variable you want to modify in a base class and mark it private. Perhaps provide a "getter" function to that member. That function would be const and would probably return a const reference to the member. Then make your function a friend of that base class. That function will be able to change the value of that private member.
If you can afford to use mutable, that is the right way to do it.
Still, it's possible to do what you are asking for. Normally this is done via the “fake this” idiom:
MyClass *mutableThis = const_cast<MyClass*>(this);
Then access your field normally through the new pointer. This is also the way to do it if you have to support some old compiler with no mutable support.
Note however that this is generally a dangerous practice, as it can easily lead you into the dreaded realm of undefined behavior. If the original object was actually declared const (as opposed to just being accessed via a const pointer/reference), you're asking for trouble.
In short: use mutable when you can, use fake this when you can't, but only when you know what you're doing.

Best way to return an object in c++?

I'm pretty noobish when it comes to c++, what is the better way of returning an object? I'm coming from the scripting world where Objects are always references, and am trying to achieve the same notion ... I'm basing this off of When to pass by reference and when to pass by pointer in C++?, where one user stated: "A good rule of thumb: "Use references when you can and pointers when you have to"."
// basic layer class
class Layer { private: Channel channel; // NEVER NULL };
// return object by pointer
Channel *Layer::getChannel() {
return &channel;
};
// return by reference
Channel& Layer::getChannel() {
return channel;
};
The problem with the second version is that the compiler will accept this line:
Channel channel = layer.getChannel(); // creates a copy BAD
when it should be:
Channel &channel = layer.getChannel(); // reference good
Is there any way to enforce a caller of the second option to force it to not create a new channel, or is the first option better anyways, even if it will never be NULL?
You need to adjust the Channel class itself so that it isn't copyable. If it is copyable, the user can copy it, and nothing you do can prevent it.
If copying is not a meaningful operation, then you can "disable" it. Simply define the copy constructor (Channel(const Channel&)) and the assignment operator (Channel& operator=(const Channel&)) to be private. Then any attempt at copying the class will result in a compile error.
On a side note, as others have mentioned, C++ is not the scripting languages you're familiar with. Everything is not a reference, and you're only setting yourself up for a world of pain by pretending otherwise. In C++, it is common to allocate objects on the stack, and pass objects by value, rather than passing references and pointers around.
Returning a reference (or const reference) is the normal way for a getter method to give the caller direct access to a member variable, so I'd recommend the second version of getChannel().
If you want to prevent callers from making inappropriate copies of Channel, you can accomplish that by making its copy constructor private. (If you want to prevent everything from making copies, even Channel itself, you can declare the constructor private and then not implement it.) But you should only do this if making a copy would actually be nonsensical, e.g. if the class represents some sort of underlying resource that can't be copied. Don't forbid copying just because you think the caller shouldn't need to; that's the caller's decision to make.
Return a copy of the object itself when copying isn't expensive for your purposes, and when you don't need to be able to change the original. This should be the default.
Channel Layer::getChannel() { return channel; };
Return by reference or pointer when copying is expensive or when you might want to change the value. Returning by reference allows you do to things like this:
layer.getChannel().clear();
And have it act on the channel that's in that layer.
Returning a pointer is similar to returning a reference except that it gives you a little more flexibility, in that the pointer can pointer to no object at all. I often a pointer when I want to be able to use store the "channel" in another class. I'd then do
class MyClass
{
// ...
void setChannel(Channel *pC) { m_pChannel = pC; }
private:
Channel * m_pChannel; // pointer to a channel that came from layer
}
Since you're returning a reference to the object, you are giving the users of the class direct access to the object, and if you're going to do that, why are you making the object private? Just make it public.
You can't stop a caller to create a new instance even when you use the pointer-return-version.
Channel* channel = new Channel(*layer.getChannel());
I know there is a way to achieve this goal. (For example, making Channle's ctor private so only it's static member function or its friend functions can create it.) However, I don't think this is the point of your question.
The point is that when you are making the member function returning either reference or pointer, you give a caller options he can choose whether he wants to copy it or reference it. Also, you can make your intention more clear by adding const to make it read-only.
For your case, I'd go for reference-return-version as the Channel cannot be null. If you do not want them to change the member variable, return const reference. Remember there is no single best way to decide return value type as it depends on what you want to say. Hope it helps! :)
Most important is maintaining readability with the code that's around you. "When in Rome, do as the Romans do." is important. You write it once, but everyone who has to maintain your code has to read it. If all of a sudden your code follows different guidelines than everyone around you, that means they need to first figure out your style, then figure out what you're doing...
One approach I've seen work very well is having pointers for things you change and const references for things you don't:
class Passenger {
...
};
class Car {
public:
int speed() const { return speed_; }
void set_speed(int speed) { speed_ = speed; }
const Passenger& passenger() const { return pass_;}
Passenger* mutable_passenger() { return &pass_; }
private:
int speed_;
Passenger pass_;
};
Clients of this class can do:
const Passenger& pass = car.passenger(); // no copy, but don't need to deal with NULL ptrs.
Other answers suggesting making copying a compile error are good ones.

C++ reference type recommended usage

I am programming in C++ more then 5 years, and have never met any place where reference of the variable is recommended to use except as a function argument (if you don't want to copy what you pass as your function argument). So could someone point cases where C++ variable reference is recommended (I mean it gives any advantage) to use.
As a return value of an opaque collection accessor/mutator
The operator[] of std::map returns a reference.
To shorten the text needed to reference a variable
If you miss old-school with Foo do ... statement (that's Pascal syntax), you can write
MyString &name = a->very->long_->accessor->to->member;
if (name.upcase() == "JOHN") {
name += " Smith";
}
another example of this can be found in Mike Dunlavey's answer
To state that something is just a reference
References are also useful in wrapper objects and functors--i.e. in intermediate objects that logically contact no members but only references to them.
Example:
class User_Filter{
std::list<User> const& stop_list;
public: Functor (std::list<User> const& lst)
: stop_list(lst) { }
public: bool operator()(User const& u) const
{ return stop_list.exists(u); }
};
find_if(x.begin(),x.end(),User_Filter(user_list));
The idea here that it's a compile error if you don't initialize a reference in constructor of such an object. The more checks in compile time--the better programs are.
Here's a case where it's handy:
MyClass myArray[N];
for (int i = 0; i < N; i++){
MyClass& a = myArray[i];
// in code here, use a instead of myArray[i], i.e.
a.Member = Value;
}
Use references wherever you want, pointers when you are forced to.
References and pointers share part of their semantics: they are an alias to an element that is not present. The main difference is with memory managements: references express clearly that you are not responsible for the resource. On the other hand, with pointers it is never really clear (unless you mean smart pointers): are you assumed to delete the pointer or will it be deleted externally?
You must use pointers when you must manage memory, want to allow for optional semantics or need to change the element referred to at a later time.
In the rest of cases, where you can use a reference or a pointer, references are clearer and should be preferred.
Now, as you point out, they are really not needed: you can always use pointers for all the reference uses (even parameter passing), but the fact that you can use a single tool for everything does not mean there are no better suited tools for the job.
I tend to use reference members instead of pointers for externally controlled non-optional construction parameters.
EDIT (added example):
Let's say that you have a database and a DAO class having the database as a dependency:
struct Database {};
struct PersonDao {
const Database &m_d;
PersonDao(const Database &d): m_d(d) {}
};
Furthermore, the scope of the database is controlled externally from the DAO:
int main() {
Database d;
PersonDao pd(d);
}
In this case it makes sense to use a reference type, since you don't ever want DAO::m_d to be null, and its lifetime is controlled externally (from the main function in this case).
I use references in function arguments not just to avoid copies but also instead of pointers to avoid having to deal with NULL pointers where appropriate. Pointers model a "maybe there's a value, but maybe not (NULL)", references are a clear statement that a value is required.
... and to make it absolutely clear (-> comments). I tend to avoid pointers to model "maybe there are several values" - a vector is a better option here. Pointers to several values often end up in C-style programming because you usually have to pass the # of elements as well separately.
Use a const reference to give a name to a value, e.g.:
const Vec3 &ba=b-a;
This names the value, but doesn't necessarily create a variable for it. In theory, this gives the compiler more leeway and may allow it to avoid some copy constructor calls.
(Related non-duplicated Stack Overflow question at Const reference to temporary. The Herb Sutter link there has more information about this.)
The argument to the copy-constructor MUST be passed as a reference, since otherwise the copy constructor would need to call it self in an endless recursion (stack overflow).
I tend to agree, but perhaps const return values.
Well you kind of have two choices for aliasing other values(ignoring shared_ptrs and the like): pointers and references.
References must be initialized at construction to refer to something else. So semantically a reference can never be NULL. In reality, though, the underlying data can go away, giving you problems often more difficult to debug than if a pointer went away. So I'm not sure there's a real advantage here unless you were disciplined and consistent with how they were used vis-a-vis referring to items that were dynamically allocated. If you did this with pointers too, you'd avoid the same problems.
Perhaps more importantly, references can be used without thinking about all the issues that arise with pointers. This is probably the main advantage. Semantically a reference is the thing. If you guarantee as the caller/callee that the underlying memory doesn't go away, you don't have to confuse the user with any of the questions that come along with pointers (Do I need to free this? Could this be NULL? etc) and can safely use a reference for convenience.
An example of this might be a function that looks up the corresponding string for an enum,
const std::string& ConvertToString( someEnum val)
{
static std::vector< std::string > lookupTable;
if (lookupTable.empty())
{
// fill in lookup table
}
// ignoring the cast that would need to happen
return lookupTable[val]
}
Here the contract between the caller and the callee guarantees that the return type will always be there. You can safely return a reference, and avoid some of the questions that pointers invite.
References make code prettier. So use them whenever it takes a reference to beautify your code.
i would like to enlist some cases:
1) while writing singleton classes
class singleton
{
singleton();
explicit singleton(const singleton&);
singleton& operator=(const singleton&);
public:
static singleton& instance()
{
static singleton inst;
return inst;
}
};// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by Scott Meyers
it has all the benefits, but avoids using the new operator
**2)**here is no such thing as a null reference. A reference must always refer to some object. As a result, if you have a variable whose purpose is to refer to another object, but it is possible that there might not be an object to refer to, you should make the variable a pointer, because then you can set it to null. On the other hand, if the variable must always refer to an object, i.e., if your design does not allow for the possibility that the variable is null, you should probably make the variable a reference
**3)**Because a reference must refer to an object, C++ requires that references be initialized:
string& rs; // error! References must
// be initialized
string s("xyzzy");
string& rs = s; // okay, rs refers to s
Pointers are subject to no such restriction
The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it
**4)**Another important difference between pointers and references is that pointers may be reassigned to refer to different objects. A reference, however, always refers to the object with which it is initialized: ¤ Item M1, P10
string s1("Nancy");
string s2("Clancy");
string& rs = s1; // rs refers to s1
string *ps = &s1; // ps points to s1
rs = s2; // rs still refers to s1,
// but s1's value is now
// "Clancy"
ps = &s2; // ps now points to s2;
// s1 is unchanged
Stream operators are an obvious example
std::ostream & operator<< (std::ostream &, MyClass const &...) {
....
}
mystream << myClassVariable;
You obviously don't want a pointer as checking for NULL makes using an operator very tedious i.s.o. convenient
I've used a reference to an ostream instead of a pointer. I supppose that I prefer references to pointers when the class has a lot of operators.

Returning reference to a pointer- C++

Consider the following class.
class mapping_items
{
public:
mapping_items(){}
void add(const mapping_item* item) {
items_.push_back( item );
}
size_t count() const{
return items_.size();
}
const mapping_item& find(const std::string& pattern){
const mapping_item* item = // iterate vector and find item;
return *item;
}
private:
mapping_items(const mapping_items&); // not allowed
mapping_items& operator=(const mapping_items&); // not allowed
std::vector<const mapping_item*> items_;
};
C++ FAQ says,
Use references when you can, and
pointers when you have to.
So in the above example, should I return const mapping_item& or const mapping_item* ?
The reason why I chose mapping_item& is because there will be always a default return value available. I will never have null returns. So a reference makes it clear that it can't have nulls. Is this the correct design?
There is a problem - what happens if your find() function fails? If this is expected never to happen, you are OK returning a reference (and raise an exception if it happens despite the fact it shouldn't). If on the other hand it may happen (e.g. looking up a name in an address book), you should consider returning a pointer, as a pointer can be NULL, indicating the find failed.
This is seems like an appropriate design choice to me - like the C++ FAQ states - uses references when you can. IMO, unnecessary use of pointers just seems to make code harder to understand.
Yes, it's the correct design. Clients can rely on values being non-null.
On a related note, some other class is responsible for managing the lifetime of mapping_item's?
Pointers and ownership easily introduces memory leaks or worse. You might want to consider whether you actually need to store pointers, or if you can get away with copying mapping_item's instead, to avoid memory leaks. However, pointers are necessary if you need to manage subclassed mapping_item's. Pointers are advisable if instances are large or need to be shared.
If you really need pointers, consider using boost::shared_ptr<> rather than raw pointers, both inside your class and as parameter types to e.g. the add() function.
Some people say, and I agree,
use pointers if value can be NULL
and references otherwise
As to your example, I'd probably go for return const mapping_item;, so by value, to avoid having a reference to a temporary, and hope for my compiler to optimize copying away.