2010-11-10 37 views
8

Giả sử tôi có:C++ const vế trái tài liệu tham khảo

  • hạng A mà là phi copyable
  • lớp B trong đó có là thành viên, const Một & một (và mất điểm A trong constructer của nó và đặt nó trong danh sách khởi tạo của nó)
  • một hàm A GenerateA();

Điều này có nghĩa rằng nó phải được hợp lệ để làm: B (GenerateA()) ?

nghĩa là, nghĩa là const ref có nghĩa là không có bản sao A trả về được tạo ra? Và điều đó có nghĩa là phạm vi tạm thời trả lại được kéo dài cho đến khi B tồn tại?

CHỈNH SỬA: Câu hỏi bổ sung từ các nhận xét: Có thể chấp nhận trả lại A & từ GenerateA() đến A cục bộ, nếu giá trị l là một A &?

Cảm ơn!

+0

Bạn không thể giữ tham chiếu đến giá trị của cuộc đời đã kết thúc; đó là chính xác những gì sẽ xảy ra khi bạn trả về một tham chiếu đến một biến cục bộ. – GManNickG

+0

@GMan: Đó chính là ý định của câu hỏi của tôi, tức là, sử dụng tham chiếu const thay đổi tuổi thọ của đối tượng đã nói. –

Trả lời

3

Vì nó đã được quy định bởi những người khác, A GenerateA() không thể biên dịch nếu A không copyable.

Về ref const: không có, tuổi thọ của các tạm thời sẽ không được mở rộng đến tuổi thọ của B. Các tiêu chuẩn [12.2.5] nói:

Một tạm thời bị ràng buộc cho một thành viên tham chiếu trong một ctor-initializer của hàm tạo (12.6.2) vẫn tồn tại cho đến khi hàm khởi tạo khởi tạo. [...] Một ràng buộc tạm thời với giá trị trả về trong câu lệnh trả về hàm (6.6.3) vẫn tồn tại cho đến khi hàm thoát.

Vì vậy, có, kéo dài tuổi thọ tạm thời trong một số ngữ cảnh (và đôi khi thực sự hữu ích: see this article), nhưng không phải trong trường hợp bạn đã trình bày.

Về câu hỏi cuối cùng của bạn, không hợp lệ để trả lại tham chiếu đến biến cục bộ từ GenerateA() (và ràng buộc kết quả với tham chiếu const sẽ không có bất kỳ trợ giúp nào).

+0

+1, không nhận thức được khoản trợ cấp đặc biệt này. – casablanca

0

Có và không

Có, tham chiếu const sẽ liên kết với biến tạm thời. Không, tham chiếu const là các thành viên lớp không mở rộng suốt đời theo cách tham chiếu const với thời lượng tự động.

+0

Bạn có thể chỉ cho tôi phần có liên quan trong tiêu chuẩn không? Và, nó * không * làm việc. Trình biên dịch (nên, gcc không) phàn nàn về bản sao được xây dựng cho đối tượng A là riêng tư. –

+2

@John: đó là nguyên nhân của 'A' được trả về bởi bản sao từ' generateA() ', không phải bởi phần còn lại của mã. Tiêu chuẩn này yêu cầu một hàm tạo bản sao có thể truy cập (hoặc, cuối cùng, một hàm tạo di chuyển) để gọi 'generateA()'. –

+0

@Andre: Cảm ơn bạn! –

4

Nếu A không thể sao chép được, thì hàm A GenerateA() không hợp lệ vì việc trả về theo giá trị yêu cầu tạo bản sao.

Nếu hàm trả về tham chiếu thay thế (ví dụ: A &GenerateA()) và tham chiếu là đối tượng A được tạo cục bộ, nó sẽ trở thành không hợp lệ ngay khi chức năng thoát. C++ không có bất kỳ hình thức thu gom rác nào, do đó không có cách nào để "kéo dài" tuổi thọ của một đối tượng miễn là nó đang được sử dụng.

+0

Bạn có thể giải thích về điều đó không? Bản sao có cần thiết vì nó phải đưa đối tượng vào khung xếp chồng phải không? có thể chấp nhận trả lại A và từ GenerateA() cho A cục bộ, nếu giá trị lvalue là const A &? Cảm ơn! –

+2

@John Bind: Các khung ngăn xếp phụ thuộc vào việc triển khai thực hiện và không ảnh hưởng đến cách hoạt động của ngôn ngữ. Ngữ nghĩa của việc trả về theo giá trị là một bản sao được tạo ra - mặc dù trình biên dịch có thể tối ưu hóa điều này, nó vẫn là một lỗi nếu đối tượng không thể được sao chép. – casablanca

+0

@casablanca: Điều cần biết. Cảm ơn bạn. Điểm phụ: "trình biên dịch có thể tối ưu hóa" == RVO? –

0

Dưới đây là một ví dụ :

#include <iostream> 
using namespace std; 

int& GenX(bool reset) 
{ 
    static int* x = new int; 
    *x = 100; 
    if (reset) 
    { 
     delete x; 
     x = new int; 
     *x = 200; 
    } 
    return *x; 
} 

class YStore 
{ 
public: 
    YStore(int& x); 
    int& getX() { return my_x; } 
private: 
    int& my_x; 
}; 

YStore::YStore(int& x) 
: my_x(x) 
{ 
} 

int main() 
{ 
    YStore Y(GenX(false)); 
    cout << "X: " << Y.getX() << endl; 
    GenX(true); // side-effect in Y 
    cout << "X: " << Y.getX() << endl; 
    return 0; 
} 

Output:

X: 100 
X: 200 
+1

Điều này đánh bại mục đích sử dụng một tham chiếu, và tạo ra một rò rỉ bộ nhớ. – casablanca

+1

Đây là mã không hợp lệ. – GManNickG

+0

Nó lạm dụng ngôn ngữ, vâng. –

Các vấn đề liên quan