const_iterators быстрее?

Это потому, что константная ссылка может связываться как с lvalue, так и с rvalue. Это имеет смысл, поскольку помечено как const, значение не может быть изменено, даже если входное значение является r-значением. Если значение не является константным, у вас есть возможность редактировать неконстантную ссылку внутри функции. Это не имело бы никакого смысла, поскольку входные данные были r-значением.

35
задан Emil Stenström 14 February 2016 в 11:56
поделиться

8 ответов

Если ничего другого, const_iterator читает лучше, так как он говорит всем, кто читает код «Я просто перебираю этот контейнер, не перебирая содержащиеся в нем объекты».

Это огромная победа, не говоря уже о различиях в производительности.

75
ответ дан unwind 27 November 2019 в 06:23
поделиться

Я не понимаю, почему это так - константность - это проверка времени компиляции. Но очевидный ответ - написать тест.

Редактировать: Вот мой тест - он дает идентичные тайминги на моей машине:

#include <vector>
#include <iostream>
#include <ctime>
using namespace std;;


int main() {
    vector <int> v;
    const int BIG = 10000000;
    for ( int i = 0; i < BIG; i++ ) {
        v.push_back( i );
    }
    cout << "begin\n";
    int n = 0;
    time_t now = time(0);
    for ( int a = 0; a < 10; a++ ) {
        for( vector <int>::iterator it = v.begin(); it != v.end(); ++it ) {
            n += *it;
        }
    }
    cout << time(0) - now << "\n";
    now = time(0);
    for ( int a = 0; a < 10; a++ ) {
        for( vector <int>::const_iterator cit = v.begin(); cit != v.end(); ++cit ) {
            n += *cit;
        }
    }
    cout << time(0) - now << "\n";;

    return n != 0;

}
14
ответ дан 27 November 2019 в 06:23
поделиться

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

Однако, у вас может быть две ссылки на один и тот же объект, так что одна может быть const, одна не const. Затем, я думаю, ответы в этого потока на ограничительные указатели применимы: компилятор не может знать, был ли объект изменен, например, другим потоком или некоторым кодом обработки прерываний.

0
ответ дан Community 27 November 2019 в 06:23
поделиться

контейнер :: const_iterator :: operator * возвращает const T & вместо T & , поэтому компилятор может выполнять обычные оптимизации для константных объектов.

1
ответ дан tstenner 27 November 2019 в 06:23
поделиться

В наших рекомендациях по кодированию сказано, что предпочитают const_iterator

. Прочтите статью Скотта Мейерса здесь . Он объясняет, почему следует предпочесть итератор const_iterator.

6
ответ дан Shree 27 November 2019 в 06:23
поделиться

The guideline we use is:

Always prefer const over non-const

If you tend to use const object, you get used to using only constant operations on the objects you get and that is as much as using const_iterator as much as possible.

Constness has a viral property. Once you get to use it, it propagates to all your code. Your non-mutating methods become constant, and that requires using only constant operations on the attributes, and passing constant references around, that itself forces only constant operations...

To me, the performance advantage of using constant iterators over non constant iterators (if any at all) is much less important than the improvement in the code itself. Operations meant (designed) to be non-mutating are constant.

25
ответ дан 27 November 2019 в 06:23
поделиться

Они предназначены для нетривиальных контейнеров / итераторов. Разберитесь со своими привычками, и вы не потеряете работоспособность, когда это будет иметь значение.

Кроме того, есть несколько причин предпочесть const_iterator, несмотря ни на что:

  1. Использование const выражает намерение кода (т. Е. Только чтение, без изменения этих объектов).
  2. Использование const (_iterator) предотвращает случайное изменение данных. (см. выше)
  3. Некоторые библиотеки используют Отсутствие-константы begin () , чтобы пометить данные как грязные (например, OpenSG) и отправить их другим потокам / по сети при синхронизации, так что имеет реальные последствия для производительности.
  4. Кроме того, разрешение вам доступа к неконстантным функциям-членам может иметь побочные эффекты, которые вы не планируете (почти так же, как указано выше), например, отсоединение контейнеров копирования при записи от общих данных. Qt, например, делает именно это.

В качестве примера последнего пункта выше, вот отрывок из qmap.h в Qt:

inline iterator begin() { detach(); return iterator(e->forward[0]); }
inline const_iterator begin() const { return const_iterator(e->forward[0]); }

Даже если итератор и const_iterator практически эквивалентны (за исключением const ), detach () создает новую копию данных, если его используют два или более объекта. Это совершенно бесполезно, если вы собираетесь просто читать данные, которые вы указываете с помощью const_iterator .

Конечно, есть точки данных и в другом направлении:

  1. Для контейнеров STL и многих других семантических контейнеров с простым копированием это не имеет значения для производительности. Код эквивалентен . Однако умение писать понятный код и избегать ошибок побеждает.
  2. Const является вирусным, поэтому, если вы работаете с устаревшей базой кода, где const плохо (или просто не реализована), вам, возможно, придется работать с неконстантными итераторами.
  3. По-видимому, в некоторых STL до C ++ 0x есть ошибка, из-за которой const_iterators нельзя было использовать для удаления элементов () из контейнеров.
18
ответ дан 27 November 2019 в 06:23
поделиться

«Константность», как и ограничение доступа (публичный, защищенный, приватный), приносит пользу программисту больше, чем помогает в оптимизации.
Компиляторы не могут на самом деле оптимизировать для такого количества ситуаций, в которых используется const, как можно подумать, по многим причинам (например, const_cast, изменяемые члены данных, псевдонимы указателей / ссылок). Однако наиболее важной причиной здесь является то, что тот факт, что const_iterator не позволяет изменять данные, на которые он ссылается, не означает, что эти данные нельзя изменить другими способами. И если компилятор не может определить, что данные доступны только для чтения, он не сможет оптимизировать намного больше, чем это было бы для случая неконстантного итератора.
Дополнительную информацию и примеры можно найти по адресу: http://www.gotw.ca/gotw/081.htm

1
ответ дан 27 November 2019 в 06:23
поделиться
Другие вопросы по тегам:

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