Câu trả lời:
Khi bạn viết một tập tin thực thi ( .cpp
, .cxx
, vv) trình biên dịch của bạn tạo ra một đơn vị dịch thuật . Đây là tệp nguồn từ triển khai của bạn cộng với tất cả các tiêu đề bạn #include
d trong đó.
Liên kết nội bộ đề cập đến mọi thứ chỉ trong phạm vi của một đơn vị dịch thuật .
Liên kết bên ngoài đề cập đến những thứ tồn tại ngoài một đơn vị dịch thuật cụ thể. Nói cách khác, có thể truy cập thông qua toàn bộ chương trình , là sự kết hợp của tất cả các đơn vị dịch (hoặc tệp đối tượng).
const
các biến (cũng như mục đích của nó) hoàn toàn bị bỏ qua ở đây.
Như dudewat đã nói liên kết ngoài có nghĩa là biểu tượng (hàm hoặc biến toàn cục) có thể truy cập được trong suốt chương trình của bạn và liên kết bên trong có nghĩa là nó chỉ có thể truy cập được trong một đơn vị dịch thuật .
Bạn có thể kiểm soát rõ ràng mối liên kết của một biểu tượng bằng cách sử dụng extern
và static
từ khóa. Nếu liên kết không được chỉ định thì liên kết mặc định extern
dành cho các const
biểu tượng không và static
(bên trong) cho const
các biểu tượng.
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
Lưu ý rằng thay vì sử dụng static
cho liên kết nội bộ, tốt hơn là sử dụng các không gian tên ẩn danh mà bạn cũng có thể đặt class
es. Liên kết cho các không gian tên ẩn danh đã thay đổi giữa C ++ 98 và C ++ 11, nhưng điều chính là chúng không thể truy cập được từ các đơn vị dịch thuật khác.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
khai báo trong tệp khác.static
. Các biến như vậy được cho là có liên kết nội bộ .Xem xét ví dụ sau:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
khai báo f
là một hàm có liên kết ngoài (mặc định). Định nghĩa của nó phải được cung cấp sau trong tệp này hoặc trong đơn vị dịch thuật khác (được đưa ra dưới đây).max
được định nghĩa là hằng số nguyên. Các liên kết mặc định cho hằng là nội bộ . Liên kết của nó được thay đổi thành bên ngoài với từ khóa extern
. Vì vậy, bây giờ max
có thể được truy cập trong các tập tin khác.n
được định nghĩa là một biến số nguyên. Liên kết mặc định cho các biến được xác định bên ngoài các thân hàm là bên ngoài .#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max
được tuyên bố là có liên kết bên ngoài . Một định nghĩa phù hợp cho max
(với liên kết ngoài) phải xuất hiện trong một số tệp. (Như trong 1.cpp)n
được tuyên bố là có liên kết bên ngoài .z
được định nghĩa là một biến toàn cục với liên kết nội bộ .nCall
chỉ định nCall
là một biến giữ lại giá trị của nó qua các lệnh gọi đến hàm f()
. Không giống như các biến cục bộ với lớp lưu trữ tự động mặc định, nCall
sẽ chỉ được khởi tạo một lần khi bắt đầu chương trình và không chỉ một lần cho mỗi lần gọi f()
. Trình xác định lớp lưu trữ static
ảnh hưởng đến tuổi thọ của biến cục bộ chứ không phải phạm vi của nó.NB: Từ khóa static
đóng vai trò kép. Khi được sử dụng trong các định nghĩa của các biến toàn cục, nó chỉ định liên kết nội bộ . Khi được sử dụng trong các định nghĩa của các biến cục bộ, nó xác định rằng thời gian tồn tại của biến sẽ là thời lượng của chương trình thay vì là thời lượng của hàm.
Mong rằng sẽ giúp!
static
cho phép khởi tạo đơn lẻ lười biếng (có thể hữu ích nếu bạn cần một đối tượng toàn cầu nhưng phải kiểm soát khi nó được xây dựng do các vấn đề với trật tự xây dựng toàn cầu và không thể tự động phân bổ nó sử dụng new
trong khi các lược đồ khởi tạo sâu hơn có thể vượt quá những gì cần thiết cho đối tượng được đề cập; theo ngụ ý, đây chủ yếu là một vấn đề trên các hệ thống nhúng sử dụng C ++).
Hãy nói về phạm vi khác nhau trong 'C'
PHẠM VI: Về cơ bản là tôi có thể nhìn thấy một cái gì đó và bao xa.
Biến cục bộ: Phạm vi chỉ bên trong một hàm. Nó nằm trong khu vực STACK của RAM. Điều đó có nghĩa là mỗi khi một hàm được gọi là tất cả các biến là một phần của hàm đó, bao gồm các đối số hàm được tạo mới và bị hủy khi kiểm soát đi ra khỏi hàm. (Bởi vì ngăn xếp được tuôn ra mỗi khi hàm trả về)
Biến tĩnh: Phạm vi của điều này là cho một tập tin. Nó có thể truy cập mọi nơi trong tệp
mà nó được khai báo. Nó nằm trong phân khúc DATA của RAM. Vì điều này chỉ có thể được truy cập bên trong một tập tin và do đó liên kết NỘI BỘ. Bất kì
tập tin khác có thể thấy biến này. Trong thực tế, từ khóa STATIC là cách duy nhất để chúng tôi có thể giới thiệu một số mức dữ liệu hoặc hàm
ẩn trong 'C'
Biến toàn cục: Phạm vi của điều này là cho toàn bộ ứng dụng. Nó là hình thức có thể truy cập mọi nơi của ứng dụng. Các biến toàn cục cũng nằm trong phân đoạn DATA Vì nó có thể được truy cập mọi nơi trong ứng dụng và do đó Liên kết NGOẠI THẤT
Theo mặc định, tất cả các chức năng là toàn cầu. Trong trường hợp, nếu bạn cần ẩn một số chức năng trong một tệp từ bên ngoài, bạn có thể đặt tiền tố từ khóa tĩnh cho hàm. :-)
Trước khi nói về câu hỏi, tốt hơn là nên biết chính xác thuật ngữ đơn vị dịch thuật , chương trình và một số khái niệm cơ bản về C ++ (nói chung liên kết là một trong số chúng nói chung). Bạn cũng sẽ phải biết thế nào là phạm vi .
Tôi sẽ nhấn mạnh một số điểm chính, đặc biệt. những người mất tích trong câu trả lời trước.
Liên kết là một thuộc tính của một tên , được giới thiệu bởi một tuyên bố . Các tên khác nhau có thể biểu thị cùng một thực thể (thông thường, một đối tượng hoặc một chức năng). Nói về liên kết của một thực thể thường là vô nghĩa, trừ khi bạn chắc chắn rằng thực thể đó sẽ chỉ được gọi bằng tên duy nhất từ một số khai báo cụ thể (mặc dù thường là một tuyên bố).
Lưu ý một đối tượng là một thực thể, nhưng một biến thì không. Trong khi nói về mối liên kết của một biến, thực sự tên của thực thể được ký hiệu (được giới thiệu bởi một tuyên bố cụ thể) có liên quan. Liên kết của tên là một trong ba liên kết: không liên kết, liên kết nội bộ hoặc liên kết bên ngoài.
Các đơn vị dịch thuật khác nhau có thể chia sẻ cùng một khai báo theo tệp tiêu đề / nguồn (vâng, đó là cách diễn đạt của tiêu chuẩn). Vì vậy, bạn có thể giới thiệu cùng tên trong các đơn vị dịch thuật khác nhau. Nếu tên được khai báo có liên kết bên ngoài, danh tính của thực thể được gọi bằng tên cũng được chia sẻ. Nếu tên được khai báo có liên kết bên trong, cùng tên trong các đơn vị dịch khác nhau biểu thị các thực thể khác nhau, nhưng bạn có thể giới thiệu thực thể trong các phạm vi khác nhau của cùng một đơn vị dịch. Nếu tên không có liên kết, bạn chỉ đơn giản là không thể tham chiếu thực thể từ các phạm vi khác.
(Rất tiếc ... Tôi thấy những gì tôi đã gõ chỉ là lặp lại từ ngữ tiêu chuẩn ...)
Ngoài ra còn có một số điểm khó hiểu khác không được quy định trong đặc tả ngôn ngữ.
__attribute__
hoặc__declspec
) hoặc các tùy chọn trình biên dịch, và hình ảnh không phải là toàn bộ chương trình hoặc tệp đối tượng được dịch từ một đơn vị dịch, do đó không có khái niệm tiêu chuẩn nào có thể mô tả chính xác. Vì biểu tượng không phải là một thuật ngữ quy phạm trong C ++, nó chỉ là một chi tiết triển khai, mặc dù các phần mở rộng có liên quan của phương ngữ có thể đã được áp dụng rộng rãi.Các quy tắc liên kết của phạm vi không gian tên const
biến là một cái gì đó đặc biệt (và đặc biệt khác nhau để các const
đối tượng khai báo trong phạm vi tập tin bằng ngôn ngữ C mà còn có khái niệm về mối liên hệ của định danh). Do ODR được thi hành bởi C ++, điều quan trọng là không giữ nhiều hơn một định nghĩa về cùng một biến hoặc hàm xảy ra trong toàn bộ chương trình ngoại trừ các inline
hàm . Nếu không có quy tắc đặc biệt nào như vậy const
, một khai báo const
biến đơn giản nhất với bộ khởi tạo (ví dụ = xxx
) trong một tiêu đề hoặc tệp nguồn (thường là "tệp tiêu đề") được bao gồm bởi nhiều đơn vị dịch (hoặc được bao gồm bởi một đơn vị dịch nhiều lần, mặc dù hiếm khi) trong một chương trình sẽ vi phạm ODR, điều này sử dụngconst
biến như thay thế một số macro giống như đối tượng không thể.
Tôi nghĩ rằng Liên kết bên trong và bên ngoài trong C ++ đưa ra một lời giải thích rõ ràng và súc tích:
Một đơn vị dịch thuật đề cập đến một tệp thực hiện (.c / .cpp) và tất cả các tệp tiêu đề (.h / .hpp) mà nó bao gồm. Nếu một đối tượng hoặc chức năng bên trong một đơn vị dịch thuật có liên kết bên trong, thì biểu tượng cụ thể đó chỉ hiển thị cho trình liên kết trong đơn vị dịch thuật đó. Nếu một đối tượng hoặc chức năng có liên kết bên ngoài, trình liên kết cũng có thể nhìn thấy nó khi xử lý các đơn vị dịch thuật khác. Từ khóa tĩnh, khi được sử dụng trong không gian tên toàn cầu, buộc một biểu tượng phải có liên kết bên trong. Từ khóa extern dẫn đến một biểu tượng có liên kết bên ngoài.
Trình biên dịch mặc định liên kết các ký hiệu sao cho:
Các biến toàn cục không const có liên kết ngoài theo mặc định Các
biến toàn cục Const có liên kết bên trong theo mặc định
Các hàm có liên kết ngoài theo mặc định
Liên kết xác định xem các định danh có tên giống nhau tham chiếu đến cùng một đối tượng, chức năng hoặc thực thể khác, ngay cả khi các định danh đó xuất hiện trong các đơn vị dịch thuật khác nhau. Sự liên kết của một định danh phụ thuộc vào cách nó được khai báo. Có ba loại liên kết:
Chỉ C ++ : Bạn cũng có thể có liên kết giữa các đoạn mã C ++ và không C ++, được gọi là liên kết ngôn ngữ .
Nguồn: Liên kết chương trình IBM
Về cơ bản
extern linkage
biến có thể nhìn thấy trong tất cả các tập tininternal linkage
biến được hiển thị trong tập tin duy nhất.Giải thích: các biến const liên kết nội bộ theo mặc định trừ khi được khai báo là extern
external linkage
const
biến toàn cầu làinternal linkage
extern const
biến toàn cục làexternal linkage
Một tài liệu khá hay về liên kết trong C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-iternal_and_external_linkage_in_c++/
Trong C ++
Bất kỳ biến nào trong phạm vi tệp và không được lồng trong một lớp hoặc hàm, có thể nhìn thấy trong tất cả các đơn vị dịch trong một chương trình. Điều này được gọi là liên kết ngoài vì tại thời điểm liên kết, tên được hiển thị cho trình liên kết ở mọi nơi, bên ngoài đơn vị dịch thuật đó.
Biến toàn cầu và các hàm thông thường có liên kết bên ngoài.
Đối tượng tĩnh hoặc tên hàm ở phạm vi tệp là cục bộ cho đơn vị dịch. Điều đó được gọi là Liên kết nội bộ
Liên kết chỉ đề cập đến các yếu tố có địa chỉ tại thời gian liên kết / tải; do đó, khai báo lớp và biến cục bộ không có liên kết.