1

I noticed a behaviour in some library that I am compiling, which was slightly unexpected and wanted to clarify that.

There is a class which has a method of the following form:

void notify(Frame & frame);

Now, there is a caller which uses a unique_ptr as follows:

std::unique_ptr <Frame> localFrame (new Frame(rows, cols));

Now when it calls the method it does:

obj->notify(*localFrame);

So this relies on some implicit conversion of the underlying pointer to a reference.

My question is that is this cross platform and expected behaviour? Is there any use for me to do something something like:

obj->notify(*localFrame->get());
Luca
  • 8,260
  • 12
  • 71
  • 167
  • 7
    That is standard behavior. The smart pointers emulate "real" pointers closely, and by dereferencing a "real" pointer you get what it points to, and it's the same with the smart pointers. – Some programmer dude Apr 18 '18 at 12:48
  • @Someprogrammerdude Thank you for clarifying that for me. – Luca Apr 18 '18 at 12:49
  • 2
    FYI: `std::unique_ptr localFrame (new Frame(rows, cols));` should be `auto localFrame = std::make_unique(rows, cols);`. This stops a leak if something goes wrong and saves a move/copy – NathanOliver Apr 18 '18 at 12:52
  • @NathanOliver unfortunately that requires c++14 and not everybody can afford to switch immediately. And I doubt original form involves copy or move. – Slava Apr 18 '18 at 12:55
  • 1
    @Slava `std::make_unique` is trivially implementable in C++11. Just grab one of the implementations floating around :) – Quentin Apr 18 '18 at 13:00
  • @Quentin unfortunately I cannot legally implement `std::make_unique` – Slava Apr 18 '18 at 13:05
  • @Quentin I am stuck with c++ 11. – Luca Apr 18 '18 at 13:07
  • If you want to implement your own for C++11 see: https://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding. Although I stand corrected in my suggestion, `make_shared` is where you really see the savings. I'm just used to using `make_unique` to be consistent. – NathanOliver Apr 18 '18 at 13:14
  • @Slava why not? – Quentin Apr 18 '18 at 13:55
  • @Quentin I cannot introduce new names into `std` namespace. – Slava Apr 18 '18 at 14:27
  • @Slava oh, you're picking nits -- of course I meant implementing an equivalent function :p – Quentin Apr 18 '18 at 14:47
  • @Quentin no I am not, I prefer to write `std::make_shared` or `std::make_unique`, but putting it into global namespace (or some other) defeats the purpose, I do not want to change source later, so I do not see much benefits of using such function outside of `std` – Slava Apr 18 '18 at 14:56
  • @Slava it solves the potential exception safety issue with the unspecified evaluation order in expressions such as `foo(std::u_ptr(new A), std::u_ptr(new B))`. If both `new`-expressions are evaluated first, and the second one throws, the first one's result is leaked. – Quentin Apr 18 '18 at 15:00
  • @Quentin I know, but there is simpler solution, not to write such expression. Anyway what OP uses does not have such issue and there is no copy/move involved – Slava Apr 18 '18 at 15:05
  • @Slava yeah, but you have to remember that. Passing two dynamically-allocated objects to a function is not unusual. – Quentin Apr 18 '18 at 15:06
  • @Quentin maybe, but I never seen one. But having exception in middle of that is pretty unusual. Anyway creating your own function can have many headaches (not technical, organizational problems). So thanks for guys in standard, some have to deal with it. – Slava Apr 18 '18 at 15:10

1 Answers1

10

"Some implicit conversion" is std::unique_ptr::operator* which is quite a standard operator that returns a reference to the pointed-to object. You don't need to overcomplicate it.

bipll
  • 11,131
  • 1
  • 15
  • 31