2014-07-31 3 views
1

У меня нет доступа к библиотеке Boost и я пытаюсь реализовать что-то похожее на Boost any (контейнер, который может хранить несколько типов). Я нашел пример в http://learningcppisfun.blogspot.co.uk/2007/09/boostany.html, однако при компиляции я получаю ошибку сегментации. Отладка, похоже, предполагает, что это деструктор Variant, вызывающий проблему. Когда я комментирую деструктор, он работает нормально - хотя это утечка памяти. Кто-нибудь может объяснить, что происходит? Благодаря!C++ Усилить любую попытку

#include <iostream> 
#include <vector> 

using namespace std; 

class BaseHolder 
{ 
    public: 
     virtual ~BaseHolder(){} 
}; 

template<typename T> 
class HoldData : public BaseHolder 
{ 
    public: 
     HoldData(const T& t_) : t(t_){} 
     T t; 
}; 

class Variant 
{ 
public: 
    template<typename T> 
    Variant(const T& t) : data(new HoldData<T>(t)){} 
    ~Variant(){delete data;} 
    BaseHolder* data; 
}; 

int main(){ 
    vector<Variant> a; 
    int x = 10; 
    double y = 3.15; 
    a.push_back(x); 
    a.push_back(y); 

    cout << dynamic_cast<HoldData<int> *>(a[0].data)->t << endl; 
    cout << dynamic_cast<HoldData<double> *>(a[1].data)->t << endl; 

    return 0; 
} 

Выход:

10 
3.5 

ответ

1

То, что я думаю, что происходит это

  1. Нажимает INT 10 на вектор а

  2. Это вызывает вызов конструктора для темпа Variant позволяет назвать эту var1.

  3. Конструктор вызывает новые HOLDDATA (10)

  4. Теперь вектор А вызывает конструктор копирования вариантного (который автоматически поставляемый компилятор), чтобы создать вариант var2 в векторе. Конструктор копии по умолчанию является только побитовой копией, поэтому var1 и var2 имеют указатель данных, указывающий на то же место.

  5. var1 теперь выходит из области действия, а его деструктор называется удалением его указателя данных.

  6. var2 в векторе теперь имеет указатель на недопустимую память. Когда вектор a выходит из области видимости, var2 будет вызывать его деструктор и попытаться удалить память во второй раз, после чего произойдет сбой.

Вам необходимо предоставить свой собственный конструктор копий в варианте, который будет безопасно скопировать указатель HoldData.

2

У вас есть основное нарушение the rule of three.

Вы назначаете конструктор по умолчанию и де-выделяете в деструкторе. Теперь, как насчет вашего конструктора копий и оператора присваивания? Как насчет того, когда два объекта Variant указывают на одни и те же данные, а затем оба они выходят за рамки?

Поскольку векторы поддерживают внутреннюю целостность, копируя элементы вокруг и, фактически, сохраняют копии в первую очередь, должно быть ясно, что это серьезный фактор.

+0

У меня создалось впечатление, что переменные, данные которых в конечном счете указывают на (все, что есть в t), были построены по копиям, и поэтому не думал, что два объекта Variant могут указывать на одни и те же данные. Может быть, это не так? – user3685366

+0

@ user3685366: Нет, это не так. Ваша переменная-член не 't', это' data'. 'data' является указателем, и этот указатель, конечно, будет скопирован. Но оба экземпляра указывают на одно и то же. На самом деле это скорее целая цель указателей! –

Смежные вопросы