Почему структура передачи ссылкой не является общей оптимизацией?

Я предполагаю, что этот json хранится в строке, скажем, называется json ... поэтому попробуйте

string json = "...";
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
JObject innerObj = obj["unashamedohio"] as JObject;
int lolSummorLvl = (int) innerObj["summonerLevel"];
26
задан BCS 16 February 2009 в 05:22
поделиться

10 ответов

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

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

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

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

я не уверен, делает ли кто-либо (на самом деле, я был бы удивлен, делает ли любой, так как это, вероятно, не могло применяться очень часто).

, Конечно, как программист (при использовании C++) можно вынудить компилятор выполнить эту оптимизацию при помощи const& параметры, когда это возможно. Я знаю, что Вы спрашиваете, почему компилятор не может сделать этого автоматически, но я предполагаю, что это - следующая лучшая вещь.

25
ответ дан Michael Burr 15 October 2019 в 07:32
поделиться

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

double x; // using non structs, oh-well

void Foo(double d)
{
      x += d; // ok
      x += d; // Oops
}

void main()
{
     x = 1;
     Foo(x);
}
1
ответ дан BCS 15 October 2019 в 07:32
поделиться

Передача ссылкой является просто синтаксическим сахаром для pass-by-address/pointer. Таким образом, функция должна неявно разыменовать указатель для чтения значения параметра. Разыменование указателя могло бы быть более дорогим (если в цикле) затем копия структуры для копии значением.

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

2
ответ дан Chris Peterson 15 October 2019 в 07:32
поделиться

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

2
ответ дан shoosh 15 October 2019 в 07:32
поделиться

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

Ваш компилятор должен был бы обнаружить a) то нечто, не изменяет структуру; b) то нечто, не делает никакого вычисления на физическом местоположении элементов структуры; И c) это вызывающая сторона, или другой поток, порожденный вызывающей стороной, не изменяет структуру, прежде чем нечто будет закончено, работая.

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

1
ответ дан Sarah Mei 15 October 2019 в 07:32
поделиться

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

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

Это переносит упоминание, что оптимизацию, которая изменяет путь функция, называют, может только работать, когда оптимизируемая функция является внутренней к скомпилированному модулю (Вы получаете это путем объявления функции static в C и с шаблонами в C++). Оптимизатор должен зафиксировать не только функцию, но также и все извещатели. Это делает такую оптимизацию справедливо ограниченной в объеме, если Вы не делаете их во время ссылки. Кроме того, оптимизацию никогда не называли бы, когда конструктор копии вовлечен (как другие плакаты упомянули), потому что она могла потенциально изменить семантику программы, которую никогда не должен делать хороший оптимизатор.

3
ответ дан Jay Conrod 15 October 2019 в 07:32
поделиться

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

4
ответ дан Joe Erickson 15 October 2019 в 07:32
поделиться

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

10
ответ дан Aaron Digulla 15 October 2019 в 07:32
поделиться

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

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

11
ответ дан JaredPar 15 October 2019 в 07:32
поделиться

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

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

, Что Вы спрашиваете, компилятор, чтобы сделать измениться поведение из Вашего кода, который считали бы ошибкой компилятора.

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

2
ответ дан Adam Hawes 15 October 2019 в 07:32
поделиться
Другие вопросы по тегам:

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