C ++ 11移至本地const参考:范围

时间:2018-10-03 19:27:59

标签: c++ scope reference const move

对于常规局部const参考变量,范围为prolonged。这就是为什么以下代码按预期工作的原因:

#include <iostream>
#include <memory>

struct foo
{
        foo()
        {
                std::cout << "foo() @" << (void*)this << std::endl;
        }
        ~foo()
        {
                std::cout << "~foo() @" << (void*)this << std::endl;
        }
};

int main()
{
        auto const& f = std::make_shared<foo>();
        std::cout << "f = " << f.get() << std::endl;
        return 0;
}

// prints:
// foo() @0x55f249c58e80
// f = 0x55f249c58e80
// ~foo() @0x55f249c58e80

使用std::move()分配移动的对象时,这似乎无法按预期工作:

#include <iostream>
#include <memory>
#include <list>

struct foo
{
        foo()
        {
                std::cout << "foo() @" << (void*)this << std::endl;
        }
        ~foo()
        {
                std::cout << "~foo() @" << (void*)this << std::endl;
        }
};

int main()
{
        std::list<std::shared_ptr<foo>> l;
        l.push_back(std::make_shared<foo>());
        auto const& f = std::move(l.front());
        l.clear();
        std::cout << "f = " << f.get() << std::endl;
        return 0;
}

// prints
// foo() @0x564edb58fe80
// ~foo() @0x564edb58fe80
// f = 0x564edb58fe80

std::move()确实改变了范围,还是我在处理编译器错误?

将变量从auto const& f更改为auto f可解决此问题。如果我将移动包装到另一个函数中,它也可以工作:

auto const& f = [&]() { return std::move(l.front()); }();

几乎像std::move()并不具有与函数调用相同的语义,而是好像它只是一个常规变量赋值:

auto const& f = std::move(l.front());

1 个答案:

答案 0 :(得分:-1)

让我们抛开std::move()并创建此函数:

struct sometype {};

const sometype &foobar( const sometype &cref ) { return cref; }

现在我们使用它:

const sometype &ref = foobar( sometype() );

您如何看待,在这种情况下会延长临时寿命吗?不,它不会。仅当您直接分配引用时,才可以延长寿命。当它通过一个函数或通过static_caststd::move时,延长就消失了。因此,您在std::move()

上遇到了完全相同的问题
struct sometype {
    sometype() { std::cout << "ctype()" << std::endl; }
    ~sometype() { std::cout << "~ctype()" << std::endl; }
};

const sometype &foobar( const sometype &cref ) { return cref; }

int main()
{
    const sometype &cref1 = foobar( sometype() );
    sometype &&cref2 = std::move( sometype() );
    std::cout << "main continues" << std::endl;
}

输出:

ctype()
~ctype()
ctype()
~ctype()
main continues     

live example

注意:您不应该在return语句上使用std::move(),它不会给您任何东西。

更改代码。您应该记住std::move()不会移动任何东西。这是由特殊的赋值运算符或构造函数(如果为类型提供的)完成的。因此,当您编写此代码时:

const type &ref = std::move( something );

没有构造函数或赋值运算符,因此没有移动。为了使实际动作发生,您必须将其分配给变量:

type val = std::move( something );

如果可能的话,现在将搬家,否则将复制。