Кортеж RValue ссылка - PullRequest
       7

Кортеж RValue ссылка

0 голосов
/ 02 августа 2011

Следующий фрагмент кода

#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;
}

Я ожидаю, что после выхода из промежуточной области вектор разрушается и пытается разрушить кортежи в conatain.Это, в свою очередь, разрушает объекты А, но я не вижу, чтобы какие-либо объекты разрушались.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» не вызываются, когда вектор (и кортежи) разрушается?

[РЕДАКТИРОВАТЬ] @ Ховард Хиннант: Спасибо, и это имеет смысл.Что я не понимаю, так это следующее: 1) Когда я создаю кортеж с помощью значения r и помещаю его в вектор, я получаю ошибки памяти valgrind.Например,

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

во внутренней области видимости и добавление:

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

к промежуточной области видимости в приведенных выше примерах приводит к ошибкам памяти valgrind, но не к указанным выше ссылкам lvalue

2) Может кто-нибудь объяснить, почему следующее утверждение вызывает конструктор copu и непосредственный десктруктор?

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

1 Ответ

1 голос
/ 02 августа 2011

'a' и 'b' разрушаются при выходе из самой внутренней области, как показывает ваш вывод:

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

Ссылки, которые вы получаете через get в промежуточной области, висят: они ссылаютсяразрушенные объекты.Чтобы подтвердить это, наберите ~A() ноль m_a.

Когда вы покидаете промежуточную область видимости, вектор и кортежи, которые он содержит, разрушаются.Деструктор кортежа ссылок - нет.

...