2011-02-07 52 views
11

我不太清楚標準中的這一點。說我有三個文件是這樣的:內聯限定詞源於原型還是定義?

foo.h中

#include <iostream> 

inline void foo(); 

void foo() 
{ 
    std::cout << "Foo" << std::endl; 
} 

Foo.cpp中:

#include "foo.h" 

void baz(); 

int main() 
{ 
    baz(); 
    foo(); 
} 

bar.cpp

#include "foo.h" 

void baz() 
{ 
    foo(); 
} 

現在,foo的定義將被編譯爲編譯單元foo.o和bar.o.如果我理解正確,則內聯函數將避免鏈接器相互碰撞。 G ++編譯和鏈接本就好了,但鏗鏘++ 2.8我得到這個錯誤:

/tmp/cc-7RdmYP.o: In function `foo()': 
bar.cpp:(.text+0x50): multiple definition of `foo()' 
/tmp/cc-LW3id3.o:foo.cpp:(.text+0x50): first defined here 
collect2: ld returned 1 exit status 

看來,鐺++沒有看到void foo()作爲一個內聯函數。但是,如果我將內聯添加到定義中,它也可以正常工作。

我是否需要添加內聯到void foo()以便將它看作內聯函數,還是這是一個鏗鏘聲錯誤?

+0

我認爲你的意思是「定義」,而不是「聲明」。 – Maxpm 2011-02-07 18:24:32

+0

啊,是的,我傾向於混淆那些...;) – Maister 2011-02-07 18:25:37

+0

這是一個有趣的問題。 – 2011-02-07 19:25:11

回答

2
N3225

的C++ 0x草案說,在7.1.2 Function specifiers

  • clause 2: A function declaration with an inline specifier declares an inline function
  • clause 4: An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case.

所以,對我來說,它看起來像GCC是正確&鐺錯,但仍然有(苗條)的機會,事情是(是?)不同的C++ 03 ..

0

你必須在兩個地方使用inline

1

我相信,sta ndard始終允許通過至少包含一個聲明(包括inline說明符)來使函數成爲inline,但是關於何時添加第一個聲明爲時已晚,存在一些不確定性。是在定義太晚之後,還是在第一次通話之後?

我對此的推理有兩個方面,首先是7.1.1中的例子,雖然非規範性的,主要是關於存儲類的說明符,但它暗示每個聲明都不需要inline

其次,這個來自2001年的缺陷報告DR 317(2005年投票)增加了「如果函數的定義在第一次聲明之前在翻譯單元中出現爲內聯,則該程序不合格」。句子。從談話中可以清楚地知道,每個聲明都不需要inline,特別是在明確定義的成員函數inline的情況下,但在原始聲明沒有明確的inline的類體外部。

(該缺陷報告還包含我的口頭禪,inline是「不止一個提示」。)

當然,只要與外部鏈接函數是一個內聯函數由於一個或多個聲明包括一個轉換單元的inline符它必須根據的其餘部分被宣佈在所有翻譯單元inline第7.1.2/4段。

在這個問題的例子中,我認爲foo是一個內聯函數,它是有效的代碼,雖然標準的規範文本在我看來似乎不那麼清晰。

4

很可能你的clang使用C99內聯語義。在C99中,如果你的一個函數不使用「inline」或者包含「extern」,那麼定義就是一個「外部定義」,它只能在程序中出現一次。見inline in C99

在C++中,你的程序很好。在Clang SVN中,這個bug已經修復,你的程序應該可以正常工作。