У меня проблема в том, что, учитывая стандартное ::vector против T* + size_t count мой компилятор (Visual Studio 2005/VC++ 8) на самом деле будет генерировать худший код при циклическом проходе по указателю, чем при циклическом проходе тот вектор.
То есть у меня есть тестовая структура, содержащая вектор, и другая, содержащая указатель + счетчик. Теперь при написании семантически точно такой же конструкции цикла версия с std::vector значительно (то есть > 10%) быстрее, чем версия с указателем.
Ниже вы найдете код и сгенерированную сборку. Было бы здорово, если бы кто-нибудь мог объяснить, что здесь происходит.
Если вы посмотрите на сборку, то заметите, что версия с необработанным указателем генерирует немного больше инструкций. Было бы уже очень хорошо ответить, если бы кто-нибудь мог объяснить, чем эти версии семантически отличаются на уровне сборки.
И пожалуйста воздержитесь от ответов, рассказывающих меня это не должно волновать, преждевременная оптимизация, корень зла и т. д. В данном конкретном случае меня действительно волнует, и в любом случае я думаю, что это довольно интересная головоломка!

Настройки компилятора:
- Полная оптимизация (/Ox)
- Опция всей программы. = НЕТ
stdafx. ч
// Disable secure STL stuff!
#define _SECURE_SCL 0
#define _SECURE_SCL_THROWS 0
#include
#include
#include
#include
файл заголовка
// loop1.h
typedef int PodType;
const size_t container_size = 3;
extern volatile size_t g_read_size;
void side_effect();
struct RawX {
PodType* pData;
PodType wCount;
RawX()
: pData(NULL)
, wCount(0)
{ }
~RawX() {
delete[] pData;
pData = NULL;
wCount = 0;
}
void Resize(PodType n) {
delete[] pData;
wCount = n;
pData = new PodType[wCount];
}
private:
RawX(RawX const&);
RawX& operator=(RawX const&);
};
struct VecX {
std::vector
vData;
};
void raw_loop(const int n, RawX* obj);
void raw_iterator_loop(const int n, RawX* obj);
void vector_loop(const int n, VecX* obj);
void vector_iterator_loop(const int n, VecX* obj);
файл реализации
// loop1.cpp
void raw_loop(const int n, RawX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(int j=0, e=obj->wCount; j!=e; ++j) {
g_read_size = obj->pData[j];
side_effect();
}
side_effect();
}
}
void raw_iterator_loop(const int n, RawX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(PodType *j=obj->pData, *e=obj->pData+size_t(obj->wCount); j!=e; ++j) {
g_read_size = *j;
side_effect();
}
side_effect();
}
}
void vector_loop(const int n, VecX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(size_t j=0, e=obj->vData.size(); j!=e; ++j) {
g_read_size = obj->vData[j];
side_effect();
}
side_effect();
}
}
void vector_iterator_loop(const int n, VecX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(std::vector
::const_iterator j=obj->vData.begin(), e=obj->vData.end(); j!=e; ++j) {
g_read_size = *j;
side_effect();
}
side_effect();
}
}
основной файл теста
using namespace std;
volatile size_t g_read_size;
void side_effect()
{
g_read_size = 0;
}
typedef size_t Value;
template
Value average(Container const& c)
{
const Value sz = c.size();
Value sum = 0;
for(Container::const_iterator i=c.begin(), e=c.end(); i!=e; ++i)
sum += *i;
return sum/sz;
}
void take_timings()
{
const int x = 10;
const int n = 10*1000*1000;
VecX vobj;
vobj.vData.resize(container_size);
RawX robj;
robj.Resize(container_size);
std::vector raw_times;
std::vector vec_times;
std::vector rit_times;
std::vector vit_times;
for(int i=0; i!=x; ++i) {
const DWORD t1 = timeGetTime();
raw_loop(n, &robj);
const DWORD t2 = timeGetTime();
vector_loop(n, &vobj);
const DWORD t3 = timeGetTime();
raw_iterator_loop(n, &robj);
const DWORD t4 = timeGetTime();
vector_iterator_loop(n, &vobj);
const DWORD t5 = timeGetTime();
raw_times.push_back(t2-t1);
vec_times.push_back(t3-t2);
rit_times.push_back(t4-t3);
vit_times.push_back(t5-t4);
}
cout
Подробнее здесь: https://stackoverflow.com/questions/393 ... ode-genera