CPP guidelines: Reseating a smart pointer - unique-ptr

R.33 is confusing me. Can someone care to explain further? The meaning of "reseating" doesn't seem to work here. ??
R.33: Take a unique_ptr& parameter to express that a function reseats thewidget
Reason Using unique_ptr in this way both documents and enforces the function call’s reseating semantics.
Note “reseat” means “making a pointer or a smart pointer refer to a different object.”
Example
void reseat(unique_ptr&); // "will" or "might" reseat pointer
Example, bad
void thinko(const unique_ptr&); // usually not what you want

From the CPP guideline:
"reseat" means "making a reference or a smart pointer refer to a different object."
From modernescpp.com:
Let's look at each function signature in isolation. What does this
mean from the function perspective?
void share(std::shared_ptr<Widget> shaWid)
I'm for the lifetime of the function body a shared owner of the
Widget. At the begin of the function body, I will increase the
reference counter; at the end of the function, I will decrease the
reference counter; therefore, the Widget will stay alive, as long as I
use it.
void reseat(std::shared_ptr<Widget>& shaWid)
I'm not a shared owner of the Widget, because I will not change the
reference counter. I have not guaranteed that the Widget will stay
alive during the execution of my function, but I can reseat the
resource. A non-const lvalue reference is more like: I borrow the
resource and can reseat it.
void mayShare(const std::shared_ptr<Widget>& shaWid)
I only borrow the resource. Either can I extend the lifetime of the
resource nor can I reseat the resource. To be honest, you should use a
pointer (Widget*) or a reference (Widget&) as a parameter instead,
because there is no added value in using a std::shared_ptr.

Related

Why is my lambda capturing a pointer by value?

I have the following lambda
direction->addClickEventListener([=](Ref* sender){
std::unordered_map<int,int> data;
rep->getData(DIRECTION, data);
int last = data[1];
int rotation = (last + 45)%360;
LOG("l:%i r:%i",last,rotation);//Always logs l:0 r:45
direction->setRotation(rotation);
data[1] = rotation;
rep->setData(DIRECTION, data);
});
where getData is:
void getData(DATA_KEY key,std::unordered_map<int,int>& data){
//Modifies data with the appropriate values for key, for the current state of rep
}
void setData(DATA_KEY key,std::unordered_map<int,int>& data){
//Makes a copy of data stores it internally with key
}
rep is pointer, so I thought that whenever the lambda is called, the current value of data will always reflect the current state of rep. But it seems that it is always the value of whatever rep was at the time direction->addClickEventListener was called.
If I want to use the current state of rep, how ghouls I modify my lambda ?
EDIT: Since rep is a pointer, I can't can't capture by reference..
I'm not really sure what you're asking, so this might not be an answer to your problem, but it is an attempt to clarify what the problem with capturing by reference is.
It looks like you are having an event-based system. The important thing to know about events is that they can occur at any time.
Now lets say you have something like this (very simplified and pseudo-ish):
void some_function(some_type* rep)
{
add_event_listener([&]()
{
do_something(rep);
});
}
There is a very serious bug in the code above: When the event is invoked and the lambda is called, the function some_function will have returned, and therefore the scope of the local variable rep doesn't exist any more. So when rep is used in the lambda it is a reference to a variable that doesn't exist anymore (remember that rep is a local variable). That of course leads to undefined behavior.
If you capture by value instead, the pointer is copied meaning you now have two pointer variables, both pointing to the same memory. Then it doesn't matter if the first variable goes out of scope, because the second variable still is valid.
Pointer doesn't have state, methods or something. Pointer is abstract address of storage where your object is. "Reference" is synonymous to pointer in some ways, if you think in C terms, but they are different in C++ - you can pass pointer variable by reference, thus passing control over its value (not over the state of object it points to, that actually achieved by pointer). Pointer variable is also a storage, that contains value of pointer
You can pass any variable (storage) "by reference", which means that function can change value stored in that variable. In C that was done by passing pointers, but to pass pointer "by reference" they had to pass type like void** pointer to a pointer. In C++ & syntax is used to reduce the clutter.
[=] mans that all external variables are captured by value. This would allow anonymous function to read value of pointer, deference it and call methods\access fields of the objects it points to.
[&] would mean capture by reference. Pointer is variable. This would allow lamba to modify it, making it to point to other object.
If you do need only rep by reference use, [=. &rep].
How rep might be changed while lambda is running? If that happens in parallel thread, you'll probably need an atomic.
If you cannot change actual object your pointer refers to, that may mean that compiler does aliasing optimization because of illegal cast from one object to another, because casted away const modifier or low quality of implementation (that's rare) that causes aliasing optimization where it should not happen.

why shared pointer has a virtual function

It is mentioned in Scott Meyer's book that part of the overhead caused by using shared pointers is that they need virutal function to destroy the pointed object correctly. My question is why? Is this not supposed to be the responsibility of the class of that pointed object to have a virtual destructor?
Is this not supposed to be the reponsibility of the class of that pointed object to have a virtual destructor?
That would be one possible way to design a shared pointer, but std::shared_ptr allows you to do the following, even if Base does not have a virtual destructor:
std::shared_ptr<Base> p { new Derived{} };
It does this by capturing the correct deleter for the argument when the std::shared_ptr is constructed, then calls that when the reference count hits zero rather than just using delete (of course, you can pass your own custom deleter to use instead). This is commonly referred to as type erasure, and this technique is generally implemented using virtual function calls.

interface function getting rvalue pointers to initialize shared_ptr

I have a class exposing through it's interface add function:
void AddObject(Object *o);
Inside the class I maintain the objects in set<shared_ptr<Object>>.
Since I will create shared_ptr from the received pointer I thought to limit the function argument to only rvalue pointers so to make sure that the user will not delete the pointer I use. And so I'll change the function declaration to:
void AddObject(Object* &&o);
so a typical use will be:
AddObject(new Object())
preventing the user to accidentally delete pointer I hold.
I don't want to to use shared_ptr in the interface because the user is not familiar with shared_ptr.
Do you think my suggestion is a good idea?
I think this is a bad idea. I'm sure there is a reason why shared_ptr c-tor that gets a raw pointer is marked explicit instead of using r-value. In my eyes, It's better to teach the users once about smart pointers or at least teach them about using make_shared/make_unique (which are safer and, in the case of make_shared, more efficient, BTW).
BTW, why shared_ptr and not unique_ptr?
Also, why set? Even if you want to make sure you hold each pointer only once and searching a vector each time doesn't look natural enough in your code, I don't see a reason to hold the pointers sorted instead of using unordered_set.
First of all, this approach will not prevent the user from deleting the pointer. Consider this example
auto obj = new Object();
AddObject(std::move(obj));
delete obj;
Secondly, the amount of steps between calling new and the creation of shared_ptr should be as few as possible. If anything happens inside AddObject before it can create a shared_ptr, the object will never get deleted.
The same applies if there are more arguments to AddObject(). If constructing those fails, you will leak memory.
void AddObject(Object* &&o, SomeOtherObject* x);
AddObject(new Object(), xx()); // if xx() throws, memory leak will occur
Ideally you would "wrap" object creating into shared_ptr construction:
void AddObject(std::shared_ptr<Object> o);
AddObject(std::make_shared<Object>());
Either of the following methods may solve your problem.
You may append more comments for AddObject to tell users that delete the pointer they added is not allowed. This is almost enough.
Or, you could also make Object inherits from a base class which has a private destructor and a method named destroyByOwner.

State of object after std::move construction

Is it legal/proper c++0x to leave an object moved for the purpose of move-construction in a state that can only be destroyed? For instance:
class move_constructible {...};
int main()
{
move_constructible x;
move_constructible y(std::move(x));
// From now on, x can only be destroyed. Any other method will result
// in a fatal error.
}
For the record, I'm trying to wrap in a c++ class a c struct with a pointer member which is always supposed to be pointing to some allocated memory area. All the c library API relies on this assumption. But this requirement prevents to write a truly cheap move constructor, since in order for x to remain a valid object after the move it will need its own allocated memory area. I've written the destructor in such a way that it will first check for NULL pointer before calling the corresponding cleanup function from the c API, so that at least the struct can be safely destroyed after the move.
Yes, the language allows this. In fact it was one of the purposes of move semantics. It is however your responsibility to ensure that no other methods get called and/or provide proper diagnostics. Note, usually you can also use at least the assignment operator to "revive" your variable, such as in the classical example of swapping two values.
See also this question

What is a Windows Handle?

What is a "Handle" when discussing resources in Windows? How do they work?
It's an abstract reference value to a resource, often memory or an open file, or a pipe.
Properly, in Windows, (and generally in computing) a handle is an abstraction which hides a real memory address from the API user, allowing the system to reorganize physical memory transparently to the program. Resolving a handle into a pointer locks the memory, and releasing the handle invalidates the pointer. In this case think of it as an index into a table of pointers... you use the index for the system API calls, and the system can change the pointer in the table at will.
Alternatively a real pointer may be given as the handle when the API writer intends that the user of the API be insulated from the specifics of what the address returned points to; in this case it must be considered that what the handle points to may change at any time (from API version to version or even from call to call of the API that returns the handle) - the handle should therefore be treated as simply an opaque value meaningful only to the API.
I should add that in any modern operating system, even the so-called "real pointers" are still opaque handles into the virtual memory space of the process, which enables the O/S to manage and rearrange memory without invalidating the pointers within the process.
A HANDLE is a context-specific unique identifier. By context-specific, I mean that a handle obtained from one context cannot necessarily be used in any other aribtrary context that also works on HANDLEs.
For example, GetModuleHandle returns a unique identifier to a currently loaded module. The returned handle can be used in other functions that accept module handles. It cannot be given to functions that require other types of handles. For example, you couldn't give a handle returned from GetModuleHandle to HeapDestroy and expect it to do something sensible.
The HANDLE itself is just an integral type. Usually, but not necessarily, it is a pointer to some underlying type or memory location. For example, the HANDLE returned by GetModuleHandle is actually a pointer to the base virtual memory address of the module. But there is no rule stating that handles must be pointers. A handle could also just be a simple integer (which could possibly be used by some Win32 API as an index into an array).
HANDLEs are intentionally opaque representations that provide encapsulation and abstraction from internal Win32 resources. This way, the Win32 APIs could potentially change the underlying type behind a HANDLE, without it impacting user code in any way (at least that's the idea).
Consider these three different internal implementations of a Win32 API that I just made up, and assume that Widget is a struct.
Widget * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return w;
}
void * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<void *>(w);
}
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<HANDLE>(w);
}
The first example exposes the internal details about the API: it allows the user code to know that GetWidget returns a pointer to a struct Widget. This has a couple of consequences:
the user code must have access to the header file that defines the Widget struct
the user code could potentially modify internal parts of the returned Widget struct
Both of these consequences may be undesirable.
The second example hides this internal detail from the user code, by returning just void *. The user code doesn't need access to the header that defines the Widget struct.
The third example is exactly the same as the second, but we just call the void * a HANDLE instead. Perhaps this discourages user code from trying to figure out exactly what the void * points to.
Why go through this trouble? Consider this fourth example of a newer version of this same API:
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
NewImprovedWidget *w;
w = findImprovedWidget(name);
return reinterpret_cast<HANDLE>(w);
}
Notice that the function's interface is identical to the third example above. This means that user code can continue to use this new version of the API, without any changes, even though the "behind the scenes" implementation has changed to use the NewImprovedWidget struct instead.
The handles in these example are really just a new, presumably friendlier, name for void *, which is exactly what a HANDLE is in the Win32 API (look it up at MSDN). It provides an opaque wall between the user code and the Win32 library's internal representations that increases portability, between versions of Windows, of code that uses the Win32 API.
A HANDLE in Win32 programming is a token that represents a resource that is managed by the Windows kernel. A handle can be to a window, a file, etc.
Handles are simply a way of identifying a particulate resource that you want to work with using the Win32 APIs.
So for instance, if you want to create a Window, and show it on the screen you could do the following:
// Create the window
HWND hwnd = CreateWindow(...);
if (!hwnd)
return; // hwnd not created
// Show the window.
ShowWindow(hwnd, SW_SHOW);
In the above example HWND means "a handle to a window".
If you are used to an object oriented language you can think of a HANDLE as an instance of a class with no methods who's state is only modifiable by other functions. In this case the ShowWindow function modifies the state of the Window HANDLE.
See Handles and Data Types for more information.
A handle is a unique identifier for an object managed by Windows. It's like a pointer, but not a pointer in the sence that it's not an address that could be dereferenced by user code to gain access to some data. Instead a handle is to be passed to a set of functions that can perform actions on the object the handle identifies.
So at the most basic level a HANDLE of any sort is a pointer to a pointer or
#define HANDLE void **
Now as to why you would want to use it
Lets take a setup:
class Object{
int Value;
}
class LargeObj{
char * val;
LargeObj()
{
val = malloc(2048 * 1000);
}
}
void foo(Object bar){
LargeObj lo = new LargeObj();
bar.Value++;
}
void main()
{
Object obj = new Object();
obj.val = 1;
foo(obj);
printf("%d", obj.val);
}
So because obj was passed by value (make a copy and give that to the function) to foo, the printf will print the original value of 1.
Now if we update foo to:
void foo(Object * bar)
{
LargeObj lo = new LargeObj();
bar->val++;
}
There is a chance that the printf will print the updated value of 2. But there is also the possibility that foo will cause some form of memory corruption or exception.
The reason is this while you are now using a pointer to pass obj to the function you are also allocating 2 Megs of memory, this could cause the OS to move the memory around updating the location of obj. Since you have passed the pointer by value, if obj gets moved then the OS updates the pointer but not the copy in the function and potentially causing problems.
A final update to foo of:
void foo(Object **bar){
LargeObj lo = LargeObj();
Object * b = &bar;
b->val++;
}
This will always print the updated value.
See, when the compiler allocates memory for pointers it marks them as immovable, so any re-shuffling of memory caused by the large object being allocated the value passed to the function will point to the correct address to find out the final location in memory to update.
Any particular types of HANDLEs (hWnd, FILE, etc) are domain specific and point to a certain type of structure to protect against memory corruption.
A handle is like a primary key value of a record in a database.
edit 1: well, why the downvote, a primary key uniquely identifies a database record, and a handle in the Windows system uniquely identifies a window, an opened file, etc, That's what I'm saying.
Think of the window in Windows as being a struct that describes it. This struct is an internal part of Windows and you don't need to know the details of it. Instead, Windows provides a typedef for pointer to struct for that struct. That's the "handle" by which you can get hold on the window.,

Resources