从unique_ptr初始化unique_ptr const引用

时间:2017-03-05 08:08:16

标签: c++ c++11 gcc unique-ptr

我用Object初始化了一个unique_ptr。因为我想将它的引用传递给函数并且不让函数更改对象内容,所以我必须将unique_ptr<const MyObject>&传递给它。但是gcc 5.4不允许我从unique_ptr<const MyObject>&初始化uinque_ptr<MyObject>

示例代码:

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: invalid initialization of reference of type ‘std::unique_ptr<const Foo>&’ from expression of type ‘std::unique_ptr<Foo>’

有没有合理的方法呢?

2 个答案:

答案 0 :(得分:6)

有两个问题:

  • 如何constify unique_ptr的指示物。
  • 如何将非拥有指针传递给函数。

传递非拥有指针的合理方法是传递原始指针:

some_function( my_unique_ptr.get() );

或者如果它不能为null,那么你可以取消引用指针并传递引用,

some_function( *my_unique_ptr )

这意味着认可与主要问题几乎无关,但仍然是,如何做到这一点:

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

答案 1 :(得分:2)

已发布valid answer

我只想为指针可能为空的情况提供一些额外的想法。

创意1:将指针包装到带有空删除器的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

提示2:使用boost::optional传递引用但仍允许它为空。不幸的是,这不适用于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

<强>结论:

我更希望boost::optional,因为它更好地表达了意图。

相关问题