26

Say I have a struct like this:

struct S
{
int i;
double d;
std::string s;
};

Can I do this?

std::make_shared<S>(1, 2.1, "Hello")
Narek
  • 38,779
  • 79
  • 233
  • 389
  • I could compile by passing an `S` object to `make_shared` parameter too, but in brackets you need to pass not the object but the constructor parameters. – Narek Aug 17 '15 at 12:48

1 Answers1

21

No you can't, you have to define your own constructor for being able to do it.

#include <iostream>
#include <memory>
#include <string>

struct S
{
    S(int ii, double dd)
    : i(ii)
    , d(dd)
    { }
  int i;
  double d;
};

int main()
{
 // S s{1, 2.1};
  auto s = std::make_shared<S>(1, 2.1);
  //or without constructor, you have to create manually a temporary
  auto s1 = std::make_shared<S>(S{1, 2.1});

}
dau_sama
  • 4,247
  • 2
  • 23
  • 30
  • I have done the second and I done understand how it works if I have to pass constructor parameters. Why I pass an object and it works? – Narek Aug 17 '15 at 12:50
  • 1
    When you pass an object, you're invoking the structure's copy constructor. – Wyzard Aug 17 '15 at 12:54
  • 1
    signature of make shared is: make_shared(_Args&&... __args) In the second case your args are a complete object and when it gets forwarded it calls the copy constructor of the object, resulting in a new well constructed S – dau_sama Aug 17 '15 at 12:55
  • 1
    that means that the second example is actually slower than the first one, which results in only one object being created, assuming the optimizer doesn't optimize the copy. – dau_sama Aug 17 '15 at 12:55
  • 2
    @dau_sama Technically, if you pass a temporary object it will (in C++11) call the move constructor. – Chris Drew Aug 17 '15 at 14:18
  • @ChrisDrew if it will call a move constructor based on temp, the temp will be deallocated soon, right? Where will the final object point then? – Narek Aug 17 '15 at 14:25
  • 1
    @dau_sama In most cases it will not be slower after compiler applies some optimization like copy elision - see http://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization/12953145#12953145 – PiotrNycz Aug 17 '15 at 14:40
  • @Narek The default move constructor will just do a member-wise move. So in this case it will not be much different from a copy constructor. Yes, the temp will be deallocated soon, that's the whole point of move constructors. The move constructor for a `std::string` could, for example, steal the memory allocated for the other string and save a memory allocation. The temporary no longer has ownership of that memory so it is ok when the temporary is destroyed. Of course the compiler may choose to elide the move entirely. – Chris Drew Aug 17 '15 at 14:44
  • @PiotrNycz I know, it's the "in most cases" that worries me. As a coding style I usually prefer trying not to relay too much on compiler optimizations if possible. That can be up to debate of course. – dau_sama Aug 17 '15 at 15:05