Home > Enterprise >  How to construct unique_ptr<T[],D>(specialization for arrays)?
How to construct unique_ptr<T[],D>(specialization for arrays)?

Time:05-20

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;(6)

I find that unique_ptr<T[],D> has many constructors.But I don't know how to create a unique_ptr<T[],D> with function(6).Could you tell me how to call it?Thanks.

Reference:https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr

CodePudding user response:

unique_ptr cannot be copied, so doesn't have a copy constructor. Constructors 5 and 6 are move constructors, which remove pointer ownership from original object and give it to new one.

unique_ptr( unique_ptr&& u ) noexcept;  // (5)  (constexpr since C  23)

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;    // (6)  (constexpr since C  23)

In example the up6b and up6d are using the call to that function.

After the call, the smart pointers up6a and up6c do not point at object they were pointing before.

std::cout << "Example constructor(6)...\n";
{
    std::unique_ptr<Foo, D> up6a(new Foo, d); // D is copied
    std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D is moved

    std::unique_ptr<Foo, D&> up6c(new Foo, d); // D is a reference
    std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D is copied
}

Most common occurrence of move constructor invocation before C 17 was the initialization with make_unique. You easily can do this:

std::unique_ptr<int[]> a(new int[10]);
std::unique_ptr<int[]> b(std::move(a));

But if you're trying to use make_unique , the latter needs invocation of specialization for an array allocation.

std::unique_ptr<int[]> b = std::make_unique<int[]>(10);

Note, that this isn't necessary invoke move constructor mentioned above.

CodePudding user response:

You could use make_unique as shown below:

auto ptr = std::make_unique<int[]>(2);

Or

If you want to pass a custom deleter then one way would be to use std::function as shown below:

auto ptr = std::make_unique<int[]>(2);

//here we use lambda as a deleter  
std::unique_ptr<int[], std::function<void(int[])>> PTR(new int[2](), [](int*p)->void
{
    std::cout<<"lambda called"<<std::endl;
    delete[]p ;
});
std::unique_ptr<int[], std::function<void(int[])>> P2(std::move(PTR));

//or more readable
//auto P2 = std::move(PTR);

Working demo.


Using a separate function instead of lambda is also possible and trivial as shown below:

//use a free function as deleter 
void func(int p[])
{
    std::cout<<"func called"<<std::endl;
    delete[]p ;
}
int main()
{
    auto ptr = std::make_unique<int[]>(2);
    
    std::unique_ptr<int[], std::function<void(int[])>> PTR(new int[2](), func);
     std::unique_ptr<int[], std::function<void(int[])>> up6b(std::move(PTR));

//or more readable 
//auto up6b = std::move(PTR);
}


Demo

  • Related