Có bất kỳ lợi ích để xác định các biến cục bộ không đổi là tĩnh (c ++) không?


9
void Animation::playAnimation() const
{
    static const int index = 0;
    const std::string& animationFileName = 
    m_animationContainer.getAnimationName(index);
    static const int zOrder = -1;
    static bool isLooping = false;

    AnimationBank::play(animationFileName,
                        zOrder,
                        isLooping);
}

Có bất kỳ lợi ích để xác định các biến cục bộ không đổi là static? Hoặc nó là không cần thiết và thậm chí thực hành xấu.



2
... Ngoài ra, vui lòng không đăng bài chéo : stackoverflow.com/questions/44431574/ cấp "Đăng bài chéo được tán thành vì nó dẫn đến các câu trả lời bị phân tán trên mạng ..."
gnat

Câu hỏi được chỉnh sửa.
TM

Câu trả lời:


10

Ngoài câu trả lời rất hay của @ Barshe, mã được tạo cho tĩnh rất có thể tệ hơn mã cho biến cục bộ, vì vậy nếu bạn quan tâm đến lợi ích dưới mức, thì số liệu thống kê sẽ tệ hơn đối với các bộ xử lý hiện đại.

Lý do là các số liệu thống kê phải được đặt ở đâu đó trong bộ nhớ có thể được tìm thấy bởi tất cả các luồng khác và bởi tất cả các lệnh khác. Điều này về cơ bản có nghĩa là đưa chúng vào bộ nhớ toàn cầu.

Trong những năm qua, các bộ xử lý & trình biên dịch cùng nhau đã tối ưu hóa đáng kể quyền truy cập vào các biến cục bộ do mức độ phổ biến của việc sử dụng chúng, so với các biến khác, chẳng hạn như toàn cầu, thống kê và trường. Trình biên dịch có thể chọn lưu trữ một biến cục bộ trong một thanh ghi CPU và ngay cả khi nó không (vì vậy nó sử dụng ngăn xếp gọi thay thế), tất cả các ngăn xếp gần như chắc chắn trong bộ đệm. Truy cập ngăn xếp thường là chế độ địa chỉ dịch chuyển ngắn (tắt thanh ghi con trỏ ngăn xếp). Tuy nhiên, việc truy cập toàn cầu hoặc thống kê thường yêu cầu và mở rộng bù hoặc địa chỉ tuyệt đối, do đó, các hướng dẫn kết quả làm như vậy dài hơn tương đương với truy cập bộ nhớ ngăn xếp.

Tất cả những gì đang được nói, do sự kết hợp giữa tĩnh và const, trình biên dịch có thể phát hiện ra rằng nó có thể thay thế giá trị không đổi tại điểm sử dụng, vì vậy có lẽ sử dụng const làm giảm nhẹ ở trên. Tuy nhiên, đoạn trích của bạn hiển thị ít nhất một thống kê không phải là const, vì vậy có lẽ cuộc thảo luận là chủ đề.


6
Bạn có chắc chắn hằng số tĩnh phải được đưa vào bộ nhớ?
MikeMB

5

Đó không phải là một câu hỏi về lợi ích, mà là một câu hỏi về ngữ nghĩa:

  • Một biến tĩnh trong một hàm (thậm chí là một hàm thành viên), có nghĩa là biến đó được chia sẻ giữa tất cả các lệnh gọi của hàm đó. Vì vậy, một cuộc gọi của chức năng đó có tác dụng phụ đối với các cuộc gọi tiếp theo.

  • Một biến không tĩnh là duy nhất cho mỗi lần thực hiện hàm.

Vì vậy, trừ khi nó được yêu cầu cho một số lý do cụ thể và chính đáng, giữ cho các biến cục bộ không tĩnh.

Nhận xét bổ sung: Biến tĩnh cũng được chia sẻ trên các luồng khác nhau. Vì vậy, việc gọi hàm này từ nhiều hơn một luồng tại một thời điểm có thể dẫn đến các điều kiện chủng tộc và UB (ngay cả khi được gọi cho các đối tượng khác nhau).


4
Bắt đầu từ C ++ 11, tiêu chuẩn xác định luồng biến tĩnh an toàn. Mặt khác, các biến tĩnh, không phải là biến.
Teimpz

5
Đây là về hằng số. Chúng không thể thay đổi giá trị của chúng, vì vậy không có sự khác biệt về ngữ nghĩa giữa các hằng số được chia sẻ giữa nhiều lệnh gọi hàm và hàm cục bộ.
MikeMB

Sự khác biệt duy nhất là nếu việc khởi tạo có tác dụng phụ.
MikeMB

1
@MikeMB Thật vậy, câu trả lời của tôi là chung chung. Nếu đó là một const, trình tối ưu hóa sẽ truyền bá nó bằng mọi cách, cho dù đó là statichay không. Nhưng vẫn còn một sự khác biệt tinh tế: như bạn đã chỉ ra, trình khởi tạo đối tượng có thể sử dụng một số hiệu ứng phụ, do đó, việc chọn tĩnh hoặc không có thể làm sai lệch hành vi dự kiến. Vì tất cả những lý do này, tôi vẫn mạnh mẽ đề nghị sử dụng staticnếu và chỉ khi constđó thực sự là thứ gì đó thực sự được liên kết với lớp. Hiển thị ý định trong mã và để trình tối ưu hóa thực hiện công việc của nó.
Christophe

Vì vậy, về mặt ngữ nghĩa, nó không tạo ra sự khác biệt nếu biến là một hằng số và địa chỉ của nó không được lấy. Phần còn lại của câu hỏi là: bạn nên sử dụng cái nào?
dùng253751

1

Một biến cục bộ được khởi tạo hoặc xây dựng mỗi khi hàm được gọi. Các biến cục bộ được lưu trữ trên ngăn xếp và do đó thường là luồng an toàn.

Một biến cục bộ tĩnh được khởi tạo hoặc xây dựng chỉ một lần; lần đầu tiên hàm được gọi. Các biến tĩnh cục bộ không được lưu trữ trên ngăn xếp và do đó thường không an toàn cho luồng.

Một biến cục bộ const là một biến không thay đổi và được khởi tạo hoặc xây dựng mỗi khi hàm được gọi. Biến const cục bộ được lưu trữ trên ngăn xếp và do đó thường là luồng an toàn.

Một biến cục bộ const const tĩnh là một biến không thay đổi và chỉ được khởi tạo hoặc xây dựng một lần; lần đầu tiên hàm được gọi. Các biến const tĩnh cục bộ không được lưu trữ trên ngăn xếp và do đó thường không an toàn cho luồng.

Trình biên dịch có thể tối ưu hóa các biến const thành hằng số thời gian biên dịch.

Trình biên dịch có thể tối ưu hóa các biến không tĩnh bằng cách giữ chúng trong các thanh ghi thay vì trên ngăn xếp.


Tại sao các static constbiến cục bộ không phải là chủ đề an toàn? Giá trị của chúng là không đổi ngay cả khi giá trị của chúng nằm trên gan.
bánh sandwich mô hình thống nhất

@unifiedmodelingsandwich: Điều gì xảy ra nếu hai luồng thực hiện cuộc gọi đầu tiên đến chức năng cùng một lúc? Sau đó cả hai luồng sẽ cố gắng khởi tạo static constbiến đó .
Bart van Ingen Schenau

Không có trong C ++ 11, họ sẽ không. Khởi tạo động của các thống kê chức năng cục bộ là an toàn luồng.
Sebastian Redl

@BartvanIngenSchenau Kể từ C ++ 11, khởi tạo biến cục bộ tĩnh là luồng an toàn . Chữ A vẫn đúng khi nói rằng nó không an toàn trong luồng chung , nhưng sẽ chính xác hơn khi nói rằng đây chỉ là trường hợp trước C ++ 11.
bánh sandwich mô hình thống nhất

1
@unifiedmodelingsandwich: Cảm ơn thông tin. Tôi chủ yếu bị mắc kẹt trên C ++ 03 :-(
Bart van Ingen Schenau
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.