Мне было интересно, если использование классов boost.any (без RTTI) везде, где могут использоваться шаблоны, замедлит работу программы. Поскольку boost any на самом деле является оберткой вокруг шаблонного класса, можно сказать, что с современными оптимизациями компилятора это даст тот же эффект, я прав?
#include <iostream>
#include <vector>
using namespace std;
template<class T> class tpl
{
T content;
public:
tpl(const T& value) : content(value) {}
operator T() const
{
return content;
}
};
class any
{
public:
any() : content(0) {}
any(const any& other) : content(other.content -> clone()) {}
template<class T> any(const T& value) : content(new holder<T>(value))
{
}
~any()
{
delete content;
}
class placeholder
{
public:
placeholder() {}
virtual placeholder* clone() const = 0;
};
template<class T> class holder : public placeholder
{
public:
T content;
holder(const T& value) : content(value) {}
~holder() {}
placeholder* clone() const
{
return new holder<T>(content);
}
};
template<class T> operator T () const
{
return dynamic_cast<holder<T>*>(content)->content;
}
placeholder* content;
};
template<class T> void test()
{
for (int i = 0; i < 10000; ++i)
{
vector<T> a;
a.push_back(23.23);
a.push_back(3.14);
double x = (double)a[0];
}
}
Поэтому было бы правильно сказать, что:
test<any>();
Это так же быстро, как:
test<tpl<double>>();
Предполагая, что вы знаете, так же, как компилятор делает во втором примере, что boost::any
используется только как двойной в этой ситуации? (Нет RTTI для любого класса).
Меня больше интересуют аргументы за и против этого тезиса.
Кроме того, существуют ли конкретные ситуации, в которых есть разница между этими методами?
Редактировать:
Тест производительности 2:
Кажется, что разница относительно велика.
Изменить 2:
Поскольку было несправедливо сравнивать первичный тип данных double
против класса any
Я сделал новый тест:
#include "tpl_vs_any.hpp"
int main()
{
test<any>();
return 0;
}
Скорость: 1794,54 мс
#include "tpl_vs_any.hpp"
int main()
{
test<tpl<double>>();
return 0;
}
Скорость: 1715,57 мс
Протестировал его несколько раз, практически одинаковые тесты.
Поэтому было бы правильно сказать, что:
…
Это так же быстро, как:
…
Предполагая, что вы знаете, как это делает компилятор во втором примере, что boost :: any используется только как double в этой ситуации?
Нет. Текущие компиляторы не достигают такого уровня самоанализа. boost::any
будет медленнее.
Конечно, вы можете просто запустить код и убедиться в этом сами.
boost::any
внутренне содержит указатель на объект, который он выделяет new
, Одна из вещей, которая делает std::vector
значительно быстрее, чем, скажем, std::list
заключается в том, что вектор хранит все свои объекты в непрерывном хранилище в одном выделении, что, помимо очевидного сокращения накладных расходов на выделение памяти, также намного более дружественно к кешу.
Также есть детали добавления RTTI к распределению, что, как правило, тривиально, но в случае действительно небольших типов, таких как double
значительно увеличивает накладные расходы на хранение.
boost::any
не является частью стандарта; это конкретная реализация определенного шаблона. Так что вы могли бы просто сравнить его; нет других конкурирующих «стандартных реализаций».