0

I have the following simple code

class Hybrid{
   std::unique_ptr<Bcf> bndfac; 


   void constructbndFace( const int &nn){ 
      bndfac( new Bcf(nn) ); // Does not work (A)
      //std::unique_ptr<Bcf> bndfac( new Bcf(nn) ); // WORKS (B)
   }
 }

class Bcf{
   Bcf(const int nn_) : nn(nn_){}
 private:
    int nn;
 }

When I try to invoke Hybrid::constructbndFace I don't understand why the compiler complains that std::unique_ptr< Bcf >' does not provide a call operator. If I use the commented line (B) the compiler no longer complains.

My question is if I use the (B) line, would the object instantiated be accessed through my declaration in the Hybrid class, or am I doing something terribly wrong Hybrid->bndFace

ATK
  • 1,296
  • 10
  • 26
  • `bndfac( new Bcf(nn) );` -> `bndfac = std::make_unique(nn);` – UnholySheep Jul 29 '20 at 08:09
  • What should `bndfac(...)` mean inside `{ }`? Did you mean to put it into an [initializer list](https://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-lists)? – Evg Jul 29 '20 at 08:10
  • No I did not mean to have it there, since at the time I initialise Hybrid I don't know the integer `nn`. Hence I created a member function in Hybrid to construct the Bcf. In reality Hybrid has more stuff, but I have condensed it to the actual problem – ATK Jul 29 '20 at 08:13

1 Answers1

3

In you line B you create a temporary object with the name that shadows member name. Then it is destroyed at the next line with closing curved bracket.

If you want to construct bndfac object, you should replace your line B with this:

bndfac = std::make_unique<Bcf>(nn);
Vasilij
  • 1,861
  • 1
  • 5
  • 9
  • What is immediately destroyed in line B? `bndfac` is not a temporary, it is an lvalue. – Evg Jul 29 '20 at 08:19
  • @ATK, and why should it work? You can't assign (or "re-construct") `A` to `B` by `B(A)` syntax. – Evg Jul 29 '20 at 08:24
  • But I am just declaring a pointer to a class in the hybrid class. I am not constructing it. – ATK Jul 29 '20 at 08:28
  • My whole idea is that I want to declare the name, like reserve it, something similar to declaring an `extern` in C fashion, and then do create it once relevant – ATK Jul 29 '20 at 08:30
  • @ATK, this is not how C++ works. `Hybrid::bndfac` will be created in `Hybrid` constructor. Later you can only assign a new value to it using operator `=`. You can't construct it inside a member function. `std::unique_ptr bndfac(new Bcf(nn));` construct a local `bndfac` that is not related to class scope object `bndfac` at all. That object can be accessed via `this->bndfac` and still holds a null pointer. – Evg Jul 29 '20 at 08:32
  • So you can never defer a construction of a class? But by declaring a smart pointer to Bcf, I am not instantiating the object yet? I still would need an explicit `new` before the object is actually created? – ATK Jul 29 '20 at 08:35
  • 2
    @ATK, no, all subobjects are **always** constructed during object construction. The default constructor of a smart pointer just initializes it with a null pointer. You can later reassign it (using `=`) either with `std::make_unique(...)` or with `std::unique_ptr(new Bcf(...))`. You need `new` for `Bcf` (and `std::make_unique` has that `new` inside), not for the smart pointer object itself. – Evg Jul 29 '20 at 08:38
  • @Evg, bndfac is an lvalue, of course. It is destroyed at the next line, because the function ends immediately after line B. I edited my answer to make it more explicit, thank you! – Vasilij Jul 29 '20 at 08:54
  • "Immediately" is probably the wrong word. If we had more statements between that line and `}`, it would be destroyed not "immediately" but just before `}`. In my understanding, "immediately" means just after `;`, as if in `std::unique_ptr(new Bcf(nn));`. – Evg Jul 29 '20 at 08:56
  • @Evg, well, I wanted to emphasize that outside this certain function creation of an object would have no effect. But I guess, you are right one should be very careful with picking correct words in C++. – Vasilij Jul 29 '20 at 09:11