2011-11-23 20 views
18

Tôi muốn kiểm tra sự hiểu biết và kết luận của tôi về vấn đề này.Tôi có quyền nói rằng const_cast theo sau bởi sửa đổi trên một ref-to-const ràng buộc với một tạm thời là okay?


On IRC, nó đã được hỏi:

Có thể chấp nhận để const_cast một tham chiếu const đó là ràng buộc với một đối tượng tạm thời?

Dịch: ông có một ref-to-const ràng buộc với một tạm thời, và ông muốn bỏ đi const -ness của nó để sửa đổi nó.

Câu trả lời của tôi là tôi đã hỏi a similar question trước đây, nơi mà sự đồng thuận dường như là bản thân thời gian không vốn là const và do đó bạn có thể bỏ số tham chiếu bạn có cho họ và sửa đổi thông qua kết quả. Và, miễn là bản gốc ref-to-const vẫn tồn tại, điều này sẽ không ảnh hưởng đến tuổi thọ của tạm thời.

Đó là:

int main() 
{ 
    const int& x = int(3); 

    int& y = const_cast<int&>(x); 
    y = 4; 

    cout << x; 
} 
// Output: 4 
//^Legal and safe 

Tôi có phải không?


(Tất nhiên, có hoặc không mã như vậy là thực sự nên là một vấn đề hoàn toàn khác!)

+0

@Mark: Ồ, một chữ có thể là một lựa chọn tồi. Bây giờ tôi đã làm cho nó không có nghĩa đen cho câu hỏi này. –

+0

Tôi sắp sửa nói rằng không có thời gian trong mã đó. May mắn thay, tôi làm mới trang trước khi làm điều đó :) – Gorpik

+0

afaik (nhưng tôi không thể tìm thấy nó trong stadnard) nó nói một cái gì đó như "khi nó được khai báo là const, sau đó bạn có thể không đúc constness đi" ... vì vậy câu hỏi là , là một chữ được khai báo là const? Tôi không nghĩ như vậy, vì nó kết quả trong một đối tượng tạm thời, như vậy là tuyên bố như const? Tôi không có ý tưởng, nhưng ruột của tôi nói: không có – PlasmaHH

Trả lời

8

số

Thứ nhất, như xa như tôi có thể nói, cho dù đó có nghĩa là chữ cái hay không là không liên quan. Rvalues ​​các loại phi lớp luôn có phi cv đủ điều kiện loại (§3.10/9), tuy nhiên, trong §8.5.3 (khởi của một tham chiếu), chúng tôi có:

Một tham chiếu đến gõ “ CV1 T1” được khởi tạo bởi một biểu hiện của loại ‘CV2 T2’ như sau:

[...]

-

Nếu không, tạm thời kiểu ‘CV1 T1’ được tạo ra và khởi tạo từ biểu thức khởi tạo bằng cách sử dụng các quy tắc cho một bản sao không tham chiếu init ialization (8.5). Tham chiếu sau đó được liên kết với tạm thời. Nếu T1 có liên quan đến tham chiếu đến T2, thì cv1 phải có cùng trình độ cv, hoặc lớn hơn cvqualification hơn, cv2; nếu không, chương trình bị hình thành không đúng.

(. Tất cả các mối quan tâm điểm trước hoặc lvalues ​​hoặc các loại lớp)

Trong trường hợp của chúng tôi, chúng ta có:

int const& x = ...; 

Vì vậy CV1 T1int const, và đối tượng tạm thời chúng tôi tạo có loại int const.Đây là một cấp độ cao nhất const (trên đối tượng), do đó, bất kỳ nỗ lực để sửa đổi nó là hành vi không xác định.

Ít nhất đó là giải thích của tôi. Tôi muốn tiêu chuẩn này rõ ràng hơn một chút về điều này.

+0

Điều đó không chỉ làm cho 3,10/9 và 8,5,3 cùng mâu thuẫn? –

+2

@ TomalakGeret'kal Không thực sự. §3.10/9 nói về giá trị và giá trị. Một biểu thức như '3' hoặc' int (3) 'là một giá trị. §8.5.3 nói về cách để khởi tạo tham chiếu; tham chiếu không bao giờ là giá trị và phải tham chiếu cho một đối tượng. Vì vậy, §8.5.3 nói rằng trình biên dịch tạo ra một đối tượng tạm thời, được khởi tạo với giá trị rvalue và liên kết tham chiếu đến điều đó. Bạn không nhận được một tham chiếu đến một chữ số nguyên, bởi vì những thứ như vậy không tồn tại; bạn có thể tham chiếu đến đối tượng không rõ ràng, chưa được đặt tên, có loại tham chiếu (và không phải là bộ khởi tạo ). –

+0

Ah! Tôi hiểu ................. Thú vị. Sau đó, tôi đồng ý với kết luận của bạn, và tôi cho rằng điều này có nghĩa là việc kéo dài tuổi thọ của thời gian có hệ quả không may là chúng ta không thể sửa đổi chúng. –

1

Câu trả lời phụ thuộc vào cách tạm thời được tạo và cách tham chiếu được khởi tạo.

Nếu bạn đã tự tạo tạm thời làm đối tượng không phải loại const và tình huống đảm bảo rằng tham chiếu const được gắn riêng cho tạm thời bạn đã tạo, thì bạn có thể bỏ đi một cách an toàn độ chói của tham chiếu và sửa đổi đối tượng.

Mặt khác, nếu tạm thời được tạo ra hoàn toàn cho bạn bởi trình biên dịch, thì bản thân tạm thời sẽ là const. Trong trường hợp đó, việc sửa đổi tạm thời dẫn đến UB.

Thật không may, tiêu chuẩn ngôn ngữ C++ không có vẻ như đảm bảo bất kỳ tình huống nào mà phương pháp khởi tạo đầu tiên nhất thiết phải được thực hiện. Trong mọi ngữ cảnh, trình biên dịch được phép giới thiệu một bản sao tạm thời bổ sung của bản gốc tạm thời của bạn. Tạm thời mới sẽ là const (như đã nêu ở trên) và do đó không thể sửa đổi được. Cho dù điều này xảy ra hay không được thực hiện xác định, như đã nêu trong 8.5.3/5.

Vì vậy, trong trường hợp chung câu trả lời là không, trong khi câu trả lời dành riêng cho việc triển khai có thể khác.

+0

Tôi không thể tìm thấy bất cứ điều gì trong 8.5.3/5 cho biết rằng bất kỳ tạm thời nào trên RHS _không được_ rơi vào điều khoản James được trích dẫn. Bạn có thể chứng minh rằng kịch bản khác khi tôi "tạo một cách rõ ràng bản thân [tạm thời]"? –

+1

@Tomalak Geret'kal: Vâng, đối với một loại lớp 'T', nếu tôi chỉ làm' const T & r = T() ', tôi có cơ hội rằng tham chiếu sẽ được gắn trực tiếp vào' T() 'của tôi (nói 8.5.3/5), không phải là const. Trong trường hợp đó, hoàn toàn hợp pháp để loại bỏ constness và sửa đổi đối tượng. – AnT

+0

8.5.3/5 là rất lớn và, như tôi đã nói, tôi không thể tìm thấy các bước suy luận mà bạn đang sử dụng. –