Что более эффективно, я ++ или ++ я? [дубликат]

Сводка

blockquote>

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

Предположим, что следующий код является допустимым:

blockquote>

Dictionary : IDictionary, тогда что он означает:

Учитывая только [117 ], поскольку это только отличается, в Контравариантных позициях in, как и bool ContainsKey(TKey key);, вы предоставляете string, но он принимает object, что хорошо, поскольку object является базовым классом, но Ковариантным Позиции out будут проблемой, примерно как ICollection Keys {get;}, так как вы готовы вернуть любое object все, что есть в .Net C #, для типа object, но вызывающая сторона ожидает только string.

Код выше даже не скомпилирует

blockquote>

Dictionary код выше даже не скомпилирует, ваша путаница с точки зрения, если я могу назначить string введите тип object, то почему бы не Dictionary - IDictionary, просто потому что Dictionary сама по себе является открытой реализацией универсального типа, которая закрывается, когда типы назначаются перед использованием, здесь отображение для типа Dictionary, который сам может быть назначен базовому классу object, а не для отдельных типов, используемых для создания закрытой структуры данных, поэтому важно сопоставлять их, чтобы гарантировать, что все методы с типами в любой позиции могут работать без проблем .

Интересный случай IEnumerable

blockquote>

На самом деле, IEnumerable является интересным примером, он имеет ковариантный type T ], это базовый интерфейс для всех коллекций в .Net, здесь у нас может быть List, предоставленный в IEnumerable, поскольку Baseclass находится только в выходной позиции, поэтому может принять любой объект дочернего класса, фактически это несовместимость была одной из причин введения ковариации и контравариантности, в противном случае было бы невозможно выполнить присвоение с инвариантным типом, что не соответствовало ожиданиям разработчика

фрагмент кода, чтобы понять разницу:

blockquote>
void Main()
{
    var list = new List();

    var dictionary = new Dictionary();

    var isTrue = list is IEnumerable;

    isTrue.Print(); // Prints True

    isTrue = dictionary is IDictionary;

    isTrue.Print(); // Prints False

    isTrue = dictionary is IEnumerable>;

    isTrue.Print(); // Prints False, KeyValuePair is not same 
  //as KeyValuePair, there's no default compatibility

    isTrue = dictionary is IEnumerable>;

    isTrue.Print(); // Prints True
}

         
         
15
задан Peter Mortensen 1 January 2019 в 02:27
поделиться

20 ответов

я ++:

  • создают временную копию меня
  • инкрементный возврат i
  • временная копия

++ я:

  • инкрементный i

возврата i С оптимизацией на, довольно возможно, что получающийся блок идентичен, однако ++ я более эффективен.

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

48
ответ дан 30 November 2019 в 23:47
поделиться

Обычно в C++, постфикс потребует дополнительной конструкции увеличенного объекта, в то время как префикс применяется непосредственно к объекту. (Или таким образом, я читал.)

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

0
ответ дан 30 November 2019 в 23:47
поделиться

Трудно ответить на это точно, поскольку это зависит от реализации компилятора/интерпретатора.

, Но вообще говоря, можно сказать, примерно расширяют меня ++ до следующих инструкций:

COPY i to tmp
INCREMENT tmp
SAVE tmp as i

, В то время как ++ я примерно расширюсь на:

LOAD i
INCREMENT i

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

, Если Вы пробуете к подобной микрооптимизации, я был бы совет Вы для представления/измерения прежде chosing один по другому.

-1
ответ дан 30 November 2019 в 23:47
поделиться

Нет никакого права, или неправильно ответьте.

, Поскольку это зависит от:

  1. , Как это было реализовано компилятором.

  2. , На чем работает ЦП система.

  3. , Если i байт или i, двойное слово

0
ответ дан 30 November 2019 в 23:47
поделиться

Это зависит от контекста, например:

x = i++

В этом случае, 'x' будет равен 'мне', и только после того, как это будет 'я' быть увеличенным одним.

x = ++i

В этом случае, 'я' буду увеличением одним, и затем новое значение 'x' будет присвоено 'x'.

В случае 'для' цикла, существует мало очевидной разницы кроме производительности (++, я быстрее).

0
ответ дан 30 November 2019 в 23:47
поделиться

Этот Stack  Водосливный вопрос имеет большой ответ: там различие в производительности между мной ++ и ++ я в C?

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

0
ответ дан 30 November 2019 в 23:47
поделиться

Нет никакого различия. Используйте конструкцию, которая имеет большую часть смысла.

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

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

0
ответ дан 30 November 2019 в 23:47
поделиться

++ я беру тот меньше инструкции по процессору, чем я ++ в x86 блоке без оптимизации.

0
ответ дан 30 November 2019 в 23:47
поделиться

В целом более эффективно использовать ++ я, чем я ++. Простая причина этого состоит в том, что ++ я - крайне то же как

я + = 1;

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

tmp = я; я + = 1;

Это вызвано тем, что старое значение 'я' - то, к чему я ++ оцениваю. И ясно который требует большего количества работы, чем просто я + = 1;

, Но как указано выше, это не оказывает фактически никакого влияния с достаточно умным компилятором, поскольку он оптимизирует неиспользованные операции далеко. Для многих интерпретируемых языков (пример: PHP), там вероятно минимальное усиление в скорости для ++ я; Но это увеличение незначительно.

0
ответ дан 30 November 2019 в 23:47
поделиться

Это обычно легче к типу i ++, следовательно это более эффективно с точки зрения времени производительности.

Серьезно, тем не менее, если я являюсь собственным типом данных (таким как интервал, дважды, и т.д.) - никакое различие.

И это - реализация, зависевшая, если это - пользовательский тип такой как

class Type
{
    Type& operator ++(){}
    const Type& operator ++(int i){}
};  

T i;
0
ответ дан 30 November 2019 в 23:47
поделиться

Автономное "я ++"; или "++ я"; должен сгенерировать одинаково эффективный код. Различие прибывает при использовании его в выражении где "побочный эффект" играет роль.

Тем не менее было время, назад когда "все в мире Vax" и высосанные компиляторы, это ++ я, как говорили, был более эффективным что я ++, даже в "для (я = 0; я < N; ++ i)" установка типа.

0
ответ дан 30 November 2019 в 23:47
поделиться

Ну, в C++ я полагаю, что у них есть различное использование, в зависимости от того, когда Вы хотите обновленную переменную.

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

2
ответ дан 30 November 2019 в 23:47
поделиться

++ мне не нужна временная переменная для хранения материала в. Думайте о них как это:

++ я

int preIncrement(int i)
{
    i = i + 1;
    return i;
}

я ++

int i = 5; // as an example
int postIncrement(_i)
{
    int temp = _i;
    i = _i + 1;
    return temp;
}

Вижу? Постинкремент требует временной переменной. Принятие компилятора не улаживает все это для Вас, которых это почти наверняка делает.

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

2
ответ дан 30 November 2019 в 23:47
поделиться

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

2
ответ дан 30 November 2019 в 23:47
поделиться

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

интервал i; я = 1; суд < < я ++;//Возвраты 1

интервал i; я = 1; суд < < ++ я;//Возвраты 2

, Когда значение не важно, большинство компиляторов переведет и ++ я и я ++ (скажите в для цикла) в тот же код machine/VM.

7
ответ дан 30 November 2019 в 23:47
поделиться

Если я не пропускаю что-то, у них должна быть та же эффективность. Они должны оба привести к синглу, добавляет инструкция. Это - просто вопрос того, где добавить инструкция происходит: вначале или конец Вашей строки кода.

0
ответ дан 30 November 2019 в 23:47
поделиться

Это не имеет значения на современном компиляторе.

int v = i++;  

совпадает с

int v = i;
i = i + 1;

А, современный компилятор обнаружит, что v не использовано, и код для вычисления v чист (никакие побочные эффекты). Затем это удалит v и код присвоения и генерирует это

i = i + 1;
5
ответ дан 30 November 2019 в 23:47
поделиться

Это действительно имеет значение! Особенно, если Вы находитесь на C++...

++i // the prefered way, unless..
auto j = i++ // this is what you need

необходимо всегда использовать префиксную нотацию для предотвращения необходимого копирования наверху, и с C++ это имеет значение!

3
ответ дан 30 November 2019 в 23:47
поделиться

Я в другом месте искал бы потенциал оптимизации.

37
ответ дан 30 November 2019 в 23:47
поделиться

++i быстрее, потому что i++ должен сохранить i, затем увеличить его, затем возвратите хранимую сумму i. ++i просто инкременты i затем возвраты это.

// ++i
i += 1;
return i;

// i++
temp = i;
i += 1;
return temp;
0
ответ дан 30 November 2019 в 23:47
поделиться
Другие вопросы по тегам:

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