Эффективная передача станд.:: вектор

я не использую VS2008 для C++, только VB & C#, но я нахожу, что, когда intellisense прекращает работать (верный для VS2003/2005/2008) это - потому что что-то в проекте/файле повреждается - обычно неверная ссылка или код.

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

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

5
задан Benjamin Pollack 20 November 2009 в 16:48
поделиться

6 ответов

Я считаю, что этот код приводит к двойному разыменованию при доступе к элементам вектора

Не обязательно. Компиляторы довольно умны и должны уметь исключать общие подвыражения. Они могут видеть, что оператор [] не изменяет «указатель на первый элемент», поэтому им не нужно заставлять ЦП перезагружать его из памяти при каждой итерации цикла.

10
ответ дан 18 December 2019 в 06:02
поделиться

Что не так с вашей идеей, так это то, что у вас уже есть два совершенно хороших решения:

  • Передайте вектор как есть, либо по значению (когда компилятор часто удаляет копию), либо (const) ссылка и доверие компилятору исключить двойное косвенное обращение, или
  • Передать пару итераторов.

Конечно, вы можете утверждать, что пара итераторов имеет «менее естественный синтаксис», но я не согласен. Это совершенно естественно для любого, кто привык к STL. Это эффективно и дает вам именно то, что вам нужно для работы с диапазоном, используя стандартные алгоритмы или ваши собственные функции.

Пары итераторов - это обычная идиома C ++, и программист на C ++, читающий ваш код, поймет их без проблем, в то время как они будут удивлены вашими домашними обертками для векторных изображений.

Если вы » re действительно параноик по поводу производительности, передайте пару итераторов. Если синтаксис вас действительно беспокоит, передайте вектор и доверяйте компилятору.

9
ответ дан 18 December 2019 в 06:02
поделиться

В чем недостаток этой идеи?

Просто: это преждевременная оптимизация. Альтернативы: принять vector const & и использовать итераторы или передать итераторы непосредственно в функцию.

4
ответ дан 18 December 2019 в 06:02
поделиться

Передача по значению, если вы не уверены, что передача по ссылке улучшает производительность.

При передаче по значению может произойти исключение копирования, что приведет к аналогичной, если не лучшей производительности.

Дэйв написал об этом здесь:

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

1
ответ дан 18 December 2019 в 06:02
поделиться

Вы правы, здесь есть лишнее косвенное обращение. Возможно (хотя это было бы удивительно), если бы компилятор (с помощью генерации кода во время компоновки) оптимизировал его.

То, что вы предложили, иногда называется нарезкой, и в некоторых ситуациях это широко используется. Хотя в целом я не уверен, что это стоит опасностей. Вы должны быть очень осторожны, не допуская аннулирования вашего среза (или чужого).

Обратите внимание, что если вы использовали итераторы для цикла вместо индексации, вы бы разыграли ссылку только пару раз (чтобы вызвать begin () и end () ), а не n раз (для индексации в вектор).

int sum(const vector<int> &v)
{
   int s = 0;
   for (auto it = v.begin(); it != v.end(); ++it) {
       s += fn(*it);
   }
   return s;
}

(Я предполагаю, что оптимизатор поднимет end () вызовы из цикла. Вы можете сделать это явно, чтобы быть уверенным. )

Передача пары итераторов вместо самого контейнера кажется идиомой STL. Это дало бы вам больше общего, так как тип контейнера может меняться, но может меняться и количество необходимых разыменований.

2
ответ дан 18 December 2019 в 06:02
поделиться

Двойного разыменования не существует, потому что компилятор, вероятно, передаст реальный указатель на вектор в качестве аргумента, а не указатель на указатель. Вы можете просто попробовать это и проверить представление дизассемблера вашей IDE, чтобы узнать, что на самом деле происходит за кулисами:

void Method(std::vector<int> const& vec) {
 int i = vec.back();
}


void SomeOtherMethod() {
  std::vector<int> vec;
  vec.push_back(1);
  Method(vec);
}

Что здесь происходит? Вектор размещается в стеке. Первый возврат транслируется в:

push        eax  // this is the constant one that has been stored in eax
lea         ecx,[ebp-24h] // ecx is the pointer to vec on the stack
call        std::vector<int,std::allocator<int> >::push_back

Теперь мы вызываем Method (), передавая вектор const &:

lea         ecx,[ebp-24h] 
push        ecx  
call        Method (8274DC0h) 

Неудивительно, что указатель на вектор передается, поскольку ссылки являются не чем иным, как постоянно разыменованными указателями. Теперь внутри метода () снова осуществляется доступ к вектору:

mov         ecx,dword ptr [ebp+8] 
call        std::vector<int,std::allocator<int> >::back (8276100h)

Указатель вектора берется непосредственно из стека и записывается в ecx.

1
ответ дан 18 December 2019 в 06:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: