RValue参考元组

时间:2011-08-02 13:33:31

标签: rvalue-reference

以下代码

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;

class A {
int m_a;

public:
A(): m_a( 10 ) { std::cout << "Default Constructor " << m_a << ", this: " << this << std::endl; }

A( int a ): m_a( a ) { std::cout << "Main Constructor " << m_a << ", this: " << this << std::endl; }

A( const A& a ): m_a( a.m_a) { std::cout << "Copy Constructor: " << m_a << ", this: " << this << std::endl; }

A( const A&& a ): m_a( std::move(a.m_a) ) { std::cout << "RValue copy Constructor " << m_a << ", this: " << this << std::endl; }

int get() const { return m_a; }

virtual ~A() { std::cout << "Destructor " << m_a << ", this: " << this << std::endl; }
};

int main() {
{
    typedef std::tuple< A&& > MyContainer;
    std::vector< MyContainer > myVec;
    {
        A a(100);
        A b(200);

        myVec.push_back( std::make_tuple( a ) );
        myVec.push_back( std::make_tuple( b ) );
        std::cout << "Innermost scope" << std::endl;
    }

    std::cout << "Intermediate scope" << std::endl;
    auto& x = get<0>(myVec.at(0));
    auto& y = get<0>(myVec.at(1));
    std::cout << x.get() << std::endl;
    std::cout << y.get() << std::endl;
}
std::cout << "Outermost scope" << std::endl;
return 0;
}

我希望,在离开intermeidate范围时,向量会破坏并尝试在conatain中破坏元组。这反过来破坏了A的对象,但有些我怎么看不到任何对象被破坏。 Valgrind也没有显示任何内存错误。以下是使用valgrind运行时的输出     $ valgrind ./a.out

==7366== Memcheck, a memory error detector
==7366== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==7366== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==7366== Command: ./a.out
==7366==
Main Constructor 100, this: 0x7fefffc70
Main Constructor 200, this: 0x7fefffc60
Copy Constructor: 100, this: 0x7fefffcb0
Destructor 100, this: 0x7fefffcb0
Copy Constructor: 200, this: 0x7fefffcd0
Destructor 200, this: 0x7fefffcd0
Innermost scope
Destructor 200, this: 0x7fefffc60
Destructor 100, this: 0x7fefffc70
Intermediate scope
100
200
Outermost scope
==7366==
==7366== HEAP SUMMARY:
==7366==     in use at exit: 0 bytes in 0 blocks
==7366==   total heap usage: 2 allocs, 2 frees, 24 bytes allocated
==7366==
==7366== All heap blocks were freed -- no leaks are possible
==7366== 
==7366== For counts of detected and suppressed errors, rerun with: -v
==7366== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

我显然在这里遗漏了一些东西。如果在中间作用域中对“get()”的调用确实返回了适当的值(100和200),那么为什么在向量(和元组被)被破坏时不调用“A”的析构函数?

[编辑] @Howard Hinnant:谢谢,这很有道理。我不明白的是以下内容: 1)当我构造一个带有右值的元组并将其推送到向量时,我确实得到了valgrind内存错误。例如。

myVec.push_back( std::make_tuple( 10 ) );

在最里面的范围内并添加:

auto& z = get<0>(myVec.at(2));
std::cout << z.get() << std::endl;

到上面示例中的中间范围产生valgrind内存错误,但不是上面显示的左值引用。

2)有人可以解释为什么下面的语句调用了copu构造函数和一个直接的析构函数?

myVec.push_back( std::make_tuple( a ) );

1 个答案:

答案 0 :(得分:1)

当您离开Innermost范围时,

'a'和'b'被破坏,如输出所示:

Innermost scope
Destructor 200, this: 0x7fefffc60
Destructor 100, this: 0x7fefffc70
Intermediate scope

您在中级范围内通过get获得的引用是悬空的:它们引用了被破坏的对象。请~A()m_a以确认此事。

当您离开中间范围时,它所包含的向量和元组将被破坏。引用元组的析构函数是无操作。