How to assign value to the unique_ptr after declaring it?
Asked Answered
D

3

10
#include <iostream>
#include <memory> // unique_ptr

using namespace std;

int main()
{
    std::unique_ptr<char*> char_ptr;

    char_ptr = (char*)"anisha";
    return 0;
}

I want to assign some value to that unique_ptr elsewhere in the code.
This gives the following error: char_ptr = (char*)"anisha";

error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<char*>’ and ‘char*’)
     char_ptr = (char*)"anisha";

How to assign value to the unique_ptr after declaring it?

Decamp answered 27/11, 2018 at 6:44 Comment(5)
Use make_uniqueKarolynkaron
That assignment is illustrative, right? You aren't really gonna have it hold the address of a string literal?Forevermore
please show an example @StoryTeller I have forgotten.Decamp
If you want to store a char* in your smart pointer you are declaring it wrong. It should be std::unique_ptr<char> char_ptr;Bitch
If you're going to put weird pointer creation in your question, you need to adjust your question to be specific about that strange pointer allocation, otherwise the answers you get are going to either not answer your question or confuse people who see this and don't understand that the weird pointer assignment is irrelevant. Voting to close based on this oddity. Why not just use a normal pointer?Dishevel
S
4

Use std::make_unique. Here is edit to your code -

#include <iostream>
#include <memory> // unique_ptr

using namespace std;

int main()
{
    std::unique_ptr<char*> char_ptr;

    //char_ptr = (char*)"anisha";
    char_ptr = std::make_unique<char*>((char*)"anisha");
    return 0;
}
Stunner answered 27/11, 2018 at 7:7 Comment(2)
Hi what if it is c++ version is older that 14?Prentice
@susil95, then use method described in this answer.Achromat
F
2

You can't naively store a pointer to a string literal in a unique_ptr. The pointer here assumes it owns the referenced object and can free it. But it can't be owned by the pointer, since string literals have static storage duration.

If you want to store a modifiable c-string in a unique_ptr you need to alloacte and copy, you can't hit the type system over the head with a cast and carry on with your merry life.

So a utility that turns string literals to unique pointers can look like this:

template<std::size_t N>
auto literal_dup(char const (&lit)[N]) {
    auto ptr = std::make_unique<char[]>(N);
    std::copy(lit, lit + N, &ptr[0]);
    return ptr; 
}

Using it will look like this:

std::unique_ptr<char[]> c_string;
c_string = literal_dup("anisha");

We need to use the array form of unique_ptr to make sure it deallocates the buffer correctly and with no undefined behavior.

Forevermore answered 27/11, 2018 at 7:26 Comment(0)
A
0

In order to assign a new value to a std::unique_ptr use the reset() method.

However, a big word of caution regarding the use of this method is that the std::unique_ptr object will try to dispose of the managed pointer by invoking a Deleter function on the managed pointer when the std::unique_ptr object will be being destroyed or when the managed pointer will be being replaced by another value.

The default Deleter calls the delete operator with the managed pointer.

That being said, if the std::unique_ptr is used with its default Deleter, the pointer assigned to the std::unique_ptr using the reset() method must point to a memory previously obtained from a call to the new operator. Otherwise, undefined behavior will result.

#include <iostream>
#include <memory>

int main()
{
    std::unique_ptr<int> u_ptr;
    
    int * p = new int(100);

    u_ptr.reset(p);
    
    std::cout << *u_ptr << '\n'; // outputs 100

    // u_ptr goes out of scope and calls delete(p); Memory is properly deallocated.
}

But, it's possible to use a Deleter function that does nothing and in this case it will be safe to assign the value of any pointer to the std::unique_ptr. However, in this case care needs to be taken to ensure that the pointer stored in the std::unique_ptr does not outlive the object where it points to. Such usage of the unique pointer could be counterintuitive:

#include <iostream>
#include <memory>

struct fake_deleter
{
    void operator()(int *){}
};


int main()
{
    std::unique_ptr<int, fake_deleter> u_ptr;
    
    int n = 100;

    u_ptr.reset(&n);
    
    std::cout << *u_ptr << '\n'; // outputs 100

    /* u_ptr goes out of scope and calls fake_deleter(&n);
       which does nothing. This is correct in this example */
}
Achromat answered 22/2 at 1:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.