简体   繁体   English

从unique_ptr初始化unique_ptr const引用

[英]initialize unique_ptr const reference from a unique_ptr

I initialized an unique_ptr with an Object. 我用一个对象初始化了一个unique_ptr。 As i want to pass a reference of it to a function and don't let the function to change the object contents, I have to pass unique_ptr<const MyObject>& to it. 因为我想将其引用传递给函数,并且不要让该函数更改对象内容,所以我必须将unique_ptr<const MyObject>&传递给它。 But gcc 5.4 doesn't let me to initialize unique_ptr<const MyObject>& from uinque_ptr<MyObject> . 但是gcc 5.4不允许我从uinque_ptr<MyObject>初始化unique_ptr<const MyObject>&

Example Code: 示例代码:

class Foo{public int x;};
unique_ptr<Foo> foo(new Foo());
foo->x = 5;

// User shouldn't be able to touch bar contents.
unique_ptr<const Foo>& bar = foo;

C++ error: C ++错误:

error: invalid initialization of reference of type ‘std::unique_ptr<const Foo>&’ from expression of type ‘std::unique_ptr<Foo>’

So is there any reasonable way to do it? 那么有什么合理的方法吗?

There are two issues: 有两个问题:

  • How to constify the referent of a unique_ptr . 如何constify unique_ptr的引用对象。
  • How to pass a non-owning pointer to a function. 如何将非所有者指针传递给函数。

The reasonable way to pass a non-owning pointer is to pass a raw pointer: 传递非所有者指针的合理方法是传递原始指针:

some_function( my_unique_ptr.get() );

Or if it can't be null then you can dereference the pointer and pass a reference, 或者,如果不能为null,则可以取消引用指针并传递引用,

some_function( *my_unique_ptr )

This means that the constification is pretty much irrelevant to the main issue, but still, here's how to do that also: 这意味着构象与主要问题几乎没有关系,但是仍然可以通过以下方法做到这一点:

unique_ptr<Foo>         p{ new Foo() };
unique_ptr<const Foo>   q{ move( p ) };    // Moves ownership!

A valid answer has already been posted. 有效答案已经发布。

I just want to provide some additional ideas for the case that the pointer could be empty. 我只想为指针可能为空的情况提供一些其他想法。

Idea 1: Wrap the pointer into a std::shared_ptr with empty deleter: 想法1:使用空的Deleter将指针包装到std::shared_ptr

#include <iostream>
#include <memory>

struct Foo{ int x; };

void Fun( std::shared_ptr<const Foo> p ) {
    if( p )     
        std::cout << "p.x: " << p->x << std::endl;
    //won't compile:
    //delete p;
}

int main(){
    std::unique_ptr<Foo> foo(new Foo());
    foo->x = 5;

    std::shared_ptr<const Foo> bar( foo.get(), []( const Foo* ){} );
    Fun( bar );

    return 0;
}

Live Demo 现场演示

Idea 2: Use boost::optional to pass a reference but still allow it to be empty. 想法2:使用boost::optional传递引用,但仍允许其为空。 Unfortunately this doesn't work with std::optional because std::optional doesn't allow reference arguments. 不幸的是,这不适用于std::optional因为std::optional不允许引用参数。

#include <iostream>
#include <memory>
#include <boost/optional.hpp>

struct Foo{ int x; };

using OptionalFooConstRef = boost::optional<Foo const&>;

void Fun( OptionalFooConstRef p ){
    if( p )
        std::cout << "p.x: " << p->x << std::endl;
    else
        std::cout << "no foo\n";
    //won't compile:
    //delete p;
}

int main(){
    std::unique_ptr<Foo> foo(new Foo());
    foo->x = 5;

    Fun( foo ? OptionalFooConstRef( *foo ) : boost::none );

    std::unique_ptr<Foo> nofoo;
    Fun( nofoo ? OptionalFooConstRef( *nofoo ) : boost::none );

    return 0;
}

Live Demo 现场演示

Conclusion: 结论:

I would prefer boost::optional because it better expresses the intention. 我更喜欢boost::optional因为它可以更好地表达意图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM