2

I just started learning the new C++ memory model:

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

void print(unique_ptr<std::string> s) {
        std::cout << *s << " " <<  s->size() << "\n";
}

int main() {
        auto s = std::make_unique<std::string>("Hello");
        print(std::move(s));
        std::cout << *s;
        return 0;
}

Right now calling cout << *s; results in a segfault, as it should. I understand why it happens. But I also would like to know if there's a way get back the ownership. I'd like to be able to use a value after passing it to a function.

5
  • 3
    If you std::move it, then you are giving it away. If you want to keep it, then don't use std::move. Pass by reference. Commented May 9, 2019 at 22:20
  • ^ that being said, even if you decided to transfer the ownership of s, std::move may not be the best way. Take a look at unique_ptr's methods in the documentation Commented May 9, 2019 at 22:23
  • 2
    There is no such thing as code that "should result in a segfault". Incorrect code like this is described as having Undefined Behavior, which means the Standard makes no guarantees on what a decent compiler should be expected to do. So it might print "(null)", might do nothing at all, might give you nasal daemons. (Maybe once you start looking beyond the Standard to specific compilers and architectures, but then you're banking a lot on optimization choices, which can frequently change.) Commented May 9, 2019 at 22:24
  • a) unique_ptr<string> as an argument means: i'll transfer you this string. This is hardly what you want as an argument of a function. You should not use unique_ptr for arguments unless really needed. b) Use a reference, and if you're not modifying it, a const reference. const string& means: i'll pass you a string that exists (references can't be null, no null check needed) and it's mine (ownership remains on the caller) and you shouldn't modify it. string& means: it's mine, but you can touch. c) Standard pointer when it can be null (i.e. optional parameters). Commented May 10, 2019 at 0:09
  • @aschepler Specific platforms (POSIX) do define certain things that result in segfaults. (I haven't actually checked the POSIX standard though) Commented May 10, 2019 at 1:53

1 Answer 1

7

If you don't want to transfer ownership of the owned object, then don't pass the unique_ptr to the function. Instead, pass a reference or a raw pointer to the function (in modern C++ style, a raw pointer is usually understood to be non-owning). In the case where you just want to read the object, a const reference is usually appropriate:

void print(const std::string&);
// ...
print(*s);
Sign up to request clarification or add additional context in comments.

3 Comments

I see, thanks. But I read that I should use unique pointers for everything. This works: void print(unique_ptr<string> &s). So when should I use unique_ptr<string> vs unique_ptr<string>& vs string&?
@Alex You shouldn't use unique_ptr everywhere. You should ensure that every dynamically allocated resource is owned by an RAII object, such as unique_ptr or a container, that will deallocate it when it goes out of scope. If you have an object that is owned by a unique_ptr then it is fine to let it be "observed" through a raw pointer or reference.
@Alex Some help with terminology: What is ownership of resources or pointers?

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.