0

I have question. Let's have this code:

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

class Writable {
public:
    virtual ~Writable() = default;
    virtual void write(std::ostream& out) const = 0;
};

class String : public Writable {
public:
    String(const std::string& str) : m_str(str) {}
    virtual ~String() override = default;
    virtual void write(std::ostream& out) const override { out << m_str << '\n'; }
private:
    std::string m_str;
};

class Number : public Writable {
public:
    Number(double num) : m_num(num) {}
    virtual ~Number() override = default;
    virtual void write(std::ostream& out) const override { out << m_num << '\n'; }
private:
    double m_num;
};

int main() {
    std::unique_ptr<Writable> str1(new String("abc"));
    std::unique_ptr<Writable> num1(new Number(456));

    str1->write(std::cout);
    num1->write(std::cout);
}

I dont understand why unique_pointers are defined like this:

std::unique_ptr<Writable> str1(new String("abc"));

Its some kind of shorthand? Or I must do it this way? Is there some kind of equivalent? For example like:

std::unique_ptr<Writable> str1 = std::unique_ptr<String>(new String("abc"));

3 Answers 3

6

Here you are creating a new unique_ptr and initializing with a raw pointer returned by new operator.

std::unique_ptr<Writable> str1(new String("abc"));

Here you are creating a new unique_ptr and initializing with a raw pointer returned by new operator and move constructing another unique_ptr with it.

std::unique_ptr<Writable> str1 = std::unique_ptr<String>(new String("abc"));

However compiler can (most likely) perform move elison and make the above two equivalent.

The right way to initialize from c++14 and later is below

std::unique_ptr<Writable> v1 = std::make_unique<String>();
Sign up to request clarification or add additional context in comments.

Comments

1

The form of initialization in

std::unique_ptr<Writable> str1(new String("abc"));

is called direct initialization. If the constructor is marked explicit (like in explicit unique_ptr(pointer p) noexcept constructor), this form of initialization is required.

explicit constructor disables copy initialization in the form of std::unique_ptr<Writable> str1 = new String("abc");.

Comments

0

Just like you can write

std::vector<int> foo(10);

to create a vector of 10 int's

std::unique_ptr<Writable> str1(new String("abc"))

creates a std::unique_ptr<Writable> that points to a new String("abc"). It is the same as doing

std::vector<int> foo = std::vector(10);

and

std::unique_ptr<Writable> str1 = std::unique_ptr<String>(new String("abc"));

except that the later cases use copy initialization which can be different in some cases.


To save on some typing you could use

auto str1 = std::make_unique<String>("abc");

instead when you declare your unique_ptr's

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.