Câu trả lời ngắn gọn là không chỉ static
hữu ích, nó còn luôn được mong muốn.
Đầu tiên, lưu ý rằng static
và constexpr
hoàn toàn độc lập với nhau. static
xác định tuổi thọ của đối tượng trong khi thực hiện; constexpr
xác định rằng đối tượng nên có sẵn trong quá trình biên dịch. Biên dịch và thực hiện là rời rạc và rời rạc, cả về thời gian và không gian. Vì vậy, một khi chương trình được biên dịch, constexpr
không còn phù hợp.
Mỗi biến tuyên bố constexpr
là ngầm const
nhưng const
và static
gần như trực giao (trừ sự tương tác với static const
số nguyên.)
Các C++
mô hình đối tượng (§1.9) yêu cầu tất cả các đối tượng khác hơn chút-lĩnh vực chiếm ít nhất một byte của bộ nhớ và có địa chỉ; hơn nữa tất cả các đối tượng như vậy có thể quan sát được trong một chương trình tại một thời điểm nhất định phải có địa chỉ riêng biệt (đoạn 6). Điều này không hoàn toàn yêu cầu trình biên dịch tạo một mảng mới trên ngăn xếp cho mỗi lần gọi hàm với một mảng const không tĩnh cục bộ, bởi vì trình biên dịch có thể ẩn náu theo as-if
nguyên tắc miễn là nó có thể chứng minh rằng không có đối tượng nào khác có thể như vậy Được Quan sát.
Thật không may, điều đó sẽ không dễ để chứng minh, trừ khi hàm này là tầm thường (ví dụ, nó không gọi bất kỳ hàm nào khác mà phần thân không thể nhìn thấy trong đơn vị dịch) bởi vì các mảng, ít nhiều theo định nghĩa, là các địa chỉ. Vì vậy, trong hầu hết các trường hợp, const(expr)
mảng không tĩnh sẽ phải được tạo lại trên ngăn xếp ở mỗi lần gọi, điều này đánh bại điểm có thể tính toán nó trong thời gian biên dịch.
Mặt khác, một static const
đối tượng cục bộ được chia sẻ bởi tất cả các nhà quan sát và hơn nữa có thể được khởi tạo ngay cả khi chức năng mà nó được định nghĩa không bao giờ được gọi. Vì vậy, không có điều nào ở trên áp dụng, và một trình biên dịch là miễn phí không chỉ tạo ra một thể hiện duy nhất của nó; nó là miễn phí để tạo một phiên bản duy nhất của nó trong lưu trữ chỉ đọc.
Vì vậy, bạn chắc chắn nên sử dụng static constexpr
trong ví dụ của bạn.
Tuy nhiên, có một trường hợp bạn không muốn sử dụng static constexpr
. Trừ khi một constexpr
đối tượng được khai báo là ODR được sử dụng hoặc được khai báo static
, trình biên dịch hoàn toàn không bao gồm nó. Điều đó khá hữu ích, vì nó cho phép sử dụng các constexpr
mảng tạm thời thời gian biên dịch mà không làm ô nhiễm chương trình được biên dịch với các byte không cần thiết. Trong trường hợp đó, rõ ràng bạn sẽ không muốn sử dụng static
, vì static
có khả năng buộc đối tượng tồn tại trong thời gian chạy.
const
khỏi mộtconst
vật thể, chỉ từ một vậtconst X*
chỉ vào một vậtX
. Nhưng đó không phải là vấn đề; điểm quan trọng là các đối tượng tự động không thể có địa chỉ tĩnh. Như tôi đã nói,constexpr
không còn có ý nghĩa khi biên soạn xong, vì vậy không có gì để cast đi là (và hoàn toàn có thể không có gì cả, vì đối tượng thậm chí còn không được bảo đảm để tồn tại trong thời gian chạy.)