2015-10-08 2 views
0

Может ли разумный приличный компилятор отбросить эту сопзЬ статической переменнойНе используется константная статическая переменная const в классе оптимизирована?

class A{ 
    const static int a = 3; 
} 

, если он нигде не используется в скомпилированном двоичном или он не показывается в любом случае в двоичном?

+0

Я считаю, что вы действительно можете проверить это, экспериментируя. Если вы не спрашиваете, разрешено ли это * стандарту, но тогда этого не хватает [tag: language-lawyer]. – Griwes

+0

Как вы узнаете, была ли она оптимизирована? Какая разница в программе? – Barmar

+0

@Barmar: вы можете посмотреть файл с листингами языка ассемблера, сгенерированный компилятором для сборки релиза. – User5910

ответ

5

Короткий ответ: Возможно. Стандарт не говорит, что компилятор должен хранить константы (или строки, или функции, или что-то еще), если он никогда не используется.

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

Например, если функция class A находится внутри функции, компилятор может знать, что этот класс не используется в другом месте, и если константа не используется в этой функции, то она не используется нигде. Если класс находится в «глобальном» пространстве, так что его можно использовать где-то в другом месте, тогда ему нужно будет сохранить константу.

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

Как вы можете себе представить, результат также будет зависеть от того, насколько умным является компилятор (и компоновщик для LTO). Все составители должны следовать принципу «если есть сомнения».

Вы можете, конечно, поэкспериментировать и написать код, в котором вы используете эту переменную, а затем удалить ее и посмотреть, какая разница в коде сборки (например, g++ -S x.cpp или clang++ -S x.cpp и посмотреть на полученный файл xs) ,

+0

спасибо :-), который помог очень хорошо – Gabriel

+0

Я бы сказал, что если это просто 'static const', он почти полностью заменяется его значением во всех вхождениях (например,' # define'), но я могу ошибаться. – Zereges

+0

@ Zereges: Да, вполне правдоподобно. –

1

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

Компилятор не будет излучать определение для const static поля в сгенерированном файле объект, когда оба из следующих условий:

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

Ниже я расскажу о втором условии. Но теперь давайте сосредоточимся на первом. Давайте посмотрим пример. Предположим, что целевая платформа 32-бит, и мы определили следующий тип:

// In MyClassA.h 
class MyClassA{ 
public: 
    const static int MyClassAField; 
}; 

// In MyClassA.cpp (or in MyClassA.h if it was included in at most one cpp file) 
const int MyClassA::MyClassAField = 2; 

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

С другой стороны, если поле было типа double, то на 32-битной платформе инструкции не могут обрабатывать 64-битные значения. В этом случае большинство компиляторов испускает поле в объектном файле и использует инструкции SSE и записывает их в 64-разрядное значение из памяти и обрабатывает их.

Теперь я объясню второе условие. Если имеется более одного файла исходного кода, использующего это поле, его нельзя устранить (независимо от того, включено ли Whole Program Optimization (WPO) или нет), поскольку в каком-либо объектном файле должно быть указано определение поля, чтобы компоновщик мог использовать его для других объектных файлов. Однако компоновщик, если вы указали правильный переключатель, может исключить поле из сгенерированного двоичного файла.

Эта оптимизация компоновщика включена с /OPT:REF для VC++ и --gc-sections для gcc. Для icc имена коммутаторов одинаковы (/ OPT: REF в Windows и --gc-разделы в Linx и OSX). Однако компилятор должен испускать каждую функцию, статическое или глобальное поле в отдельном разделе в объектном файле, чтобы компоновщик мог его устранить.

Однако есть улов. Если поле было определенно рядной следующим образом:

class MyClassA{ 
public: 
    const static int MyClassAField = 2; 
}; 

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

Когда оптимизация отключена, будет ли поле const static исключено или не зависит от компилятора, но, вероятно, оно не будет устранено.

Смежные вопросы