1

我正在使用代码来理解 c++ 中的内部和外部链接。我想出了代码,其输出似乎根据链接的顺序而有所不同。


测试1.cpp

#include<iostream>
using namespace std;
inline int c()
{
     static int p=0;
     p++;
     return p;
}
void a()
{
     cout<<"\nIn function a() , c = "<<c();
}


测试2.cpp

#include<iostream>
using namespace std;

inline int c()
{
    static int p=12;
    p++;
    return p;
}

void b()
{
       cout<<"\nIn function b() , c = "<<c();
} 


驱动程序.cpp

#include<iostream>
using namespace std;

void a();
void b();
int c();

int main()
{
   b();
   a();
   a();
   b();
   cout<<"\nIn function main() = , c "<< c();
   cout<<"\n";
}

输出1:-

when compiles as follows :- 

bash#>g++ -c test1.cpp
bash#>g++ -c test2.cpp
bash#>g++ -c driver.cpp

bash#>g++ -o out driver.o test1.o test2.o
bash#>./out

In function b() , c = 1
In function a() ,  c = 2
In function a() ,  c = 3
In function b() , c = 4
IN main() , c = 5

在上面的输出中,编译器正在考虑在 test1.cpp 中定义的 c()

输出 2:- 在链接时更改 test1.o 和 test2.o 的顺序。

bash#>g++ -o out driver.o test2.o test1.o

In function b() , c = 13
In function a() ,  c = 14
In function a() ,  c = 15 
In function b() , c = 16
IN main() , c = 17

在上面的输出中,编译器正在考虑在 test2.cpp 中定义的 c()

当我对代码进行细微更改时,我感到很困惑,如下所示:-
1)如果我不调用函数 a() [test1.cpp] 中的 c() 和函数 b()[test2.cpp] 中的 c()。 cp]

//test1.cpp changes
void a()
{
   cout<<"\nIn function a() , c = "; // not calling c()
}

//test2.cpp changes
void b()
{
    cout<<"\nIn function b() , c = "; // not calling c()
} 

链接时出现以下错误:-

bash#>g++ -o out driver.o test1.o test2.o
driver.o: In function `main':
driver.cpp:(.text+0x1f): undefined reference to `c()'
collect2: ld returned 1 exit status

2)如果我在任何一个文件中调用 c() ,即在 test1.cpp 或 test2.cpp 中,那么我不会得到链接器错误。

谁能帮助我理解这种行为。

提前致谢。

4

1 回答 1

3

您的程序具有未定义的行为,因为它违反了单一定义规则。两个不同的翻译单元正在定义具有相同名称和签名但具有不同主体的函数。

根据 C++11 标准的第 3.2/6 段:

[...] 给定这样一个D 在多个翻译单元中定义的实体,那么

— 每个定义D应由相同的标记序列组成;和

[...]

您的程序也是格式错误的,因为函数c()声明为inlineintest1.cpptest2.cpp,但不是 in driver.cpp。根据第 7.1.2/4 段

[...] 如果在一个翻译单元中声明了具有外部链接的函数inline,则应inline在其出现的所有翻译单元中声明该函数;不需要诊断。[...]

不需要诊断”位意味着编译器(或链接器)可能会或可能不会报告违反此规则的错误。这意味着你必须非常小心地打破它。

于 2013-05-26T15:57:20.417 回答