изменение привязки встроенной функции

Я только что создал два файла для проверки связи встроенной функции, первый

#include <iostream>
using namespace std;
inline int f1(int a,int b){
  a=a+b;
  while(a!=0)
    a--;
  cout<<"inline";
  return a;
}

второй:

int main(){
  extern void f1(int a,int b);
  f1(1,2);
}

g++ frist.cc second.cc

undefined reference to `f1(int, int)'

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


но когда я добавляю функцию вызова встроенной функции в первый файл:

#include <iostream>
using namespace std;
inline int f1(int a,int b){
  a=a+b;
  while(a!=0)
    a--;
  cout<<"inline";
  return a;
}
int callf1(){
  f1(10,2);
}

и снова скомпилировать, он прошел и может работать без ошибок, поэтому я хочу спросить, что здесь произошло?


person dongjk    schedule 16.11.2011    source источник


Ответы (2)


что здесь произошло?

Когда компилятор компилирует встроенную функцию, он может решить, встраивать ее или нет, в зависимости от ряда эвристик и текущего уровня оптимизации. inline — это всего лишь предложение, которое компилятор может игнорировать по своему усмотрению.

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

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

person Employed Russian    schedule 16.11.2011
comment
добавлен слабый символ, когда есть функция вызова встроенной функции, см.: 00000000 **W** _Z2f1ii - person dongjk; 16.11.2011

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

из С++ 7.1.2

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

3.2 относится к правилу одного определения.

Итак, то, что вы испытываете, не является стандартным поведением С++.

person parapura rajkumar    schedule 16.11.2011
comment
хорошо, я использую -std=c++98, чтобы попробовать еще раз, но все равно прошло... почему? - person dongjk; 16.11.2011
comment
В версии 9.2 c++98... указано, что комбинация внешней компоновки и встраивания запрещена, чтобы упростить жизнь разработчикам компиляторов - person parapura rajkumar; 16.11.2011