2017-01-18 42 views
7

Trong khi đọc phần này của C++ 14 (a free draft N4141, closest to C++14):Quy tắc lớp học địa phương có phù hợp với khấu trừ loại khấu trừ C++ 14 không?

9,8 tờ khai lớp địa phương [class.local]

[..] Tên của một lớp địa phương là địa phương kèm theo của nó phạm vi. [..]

Tuyên bố trong một lớp địa phương không được sử dụng odr (3.2) một biến với thời gian lưu trữ tự động từ một phạm vi kèm theo. [Ví dụ:

//[..] 
void f() 
{ 
    static int s ; 
    int x; 
    // [..] 
    struct local { 
     int g() { return x; } // error: odr-use of automatic variable x 
     int h() { return s; } // OK 
     // [..] 
    }; 
} 
local* p = 0; // error: local not in scope 

-end dụ]

tôi nhận thấy rằng, đầu tiên - Tôi có thể xác định p với trích tự động giá trị trả về:

auto f() 
{ 
    static int s; 
    int x; 
    struct local 
    { 
    int h() { return s; } 
    }; 
    return local{}; 
} 
decltype(f())* p = 0; // OK - ignored, that local is not in scope! 

Có lẽ nó có vẻ ok, tại sao không sử dụng kiểu cục bộ bằng cách suy ra nó từ giá trị trả về hàm, nhưng - dường như theo cách này tôi có thể truy cập biến địa phương s trước khi nó được xây dựng:

struct TalkativeInt 
{ 
    TalkativeInt() : value() 
    { 
     std::cout << "TalkativeInt()\n"; 
    } 
    TalkativeInt(int value) : value(value) 
    { 
     std::cout << "TalkativeInt(" << value << ")\n"; 
    } 

    int value; 
}; 

auto f() 
{ 
    static TalkativeInt s = 7; 
    int x; 
    struct local 
    { 
    auto h() { return s.value; } 
    }; 
    return local{}; 
} 
decltype(f())* p = 0; 

int main() { 
    decltype(f()) l; 
    std::cout << l.h(); 
} 

Output chỉ là ::

0 

Nhưng người ta có thể mong đợi:

TalkativeInt(7) 
7 

Cả kêu vang và gcc không phản đối bất kỳ cách nào, xem demo.

Tôi tự hỏi, có lẽ trường hợp như vậy cần được đề cập bằng cách nào đó hoặc trong

9,8 tờ khai lớp địa phương [class.local]

hoặc trong

7.1.6.4 auto specifier [dcl.spec.auto]

? Tất nhiên, tôi cảm thấy rằng đọc (và viết) từ biến trước khi nó được xây dựng là điều xấu, nhưng tôi đã không tìm thấy bất cứ điều gì về điều đó trong tiêu chuẩn - có lẽ, nó đã không thể trước khi C + + 14? Hoặc có một số quy tắc cơ bản tôi chỉ bỏ qua?

+2

Ouch, thật khó chịu. Điều này trông giống như một lỗ hổng, và có thể kích hoạt hành vi không xác định ... – Quentin

+1

Hmm. "Khai báo lớp địa phương" chỉ nói về tên không hiển thị bên ngoài. Điều đó không nhất thiết có nghĩa là loại không thể được sử dụng bên ngoài như tôi thấy nó. Tôi không hoàn toàn chắc chắn như thế nào bạn sẽ làm cho việc sử dụng một chức năng như vậy trước C++ 11 như bạn thậm chí không thể tuyên bố nó với 'local' là địa phương. Nhưng có lẽ tôi chỉ thiếu điểm ở đây. –

+1

§9.8 chỉ nói rằng _name_ là địa phương. Nó không phải là một điều mới mà bạn có thể sử dụng một thực thể mà không đánh vần tên của nó. – cpplearner

Trả lời

8

Nguyên tắc cho các biến cục bộ tĩnh là plain and simple:

động khởi tạo của một biến khối phạm vi với tĩnh lưu trữ thời gian (3.7.1) hoặc thời gian lưu trữ chủ đề (3.7.2) được thực hiện các kiểm soát lần đầu tiên đi qua tuyên bố của nó; biến số như vậy là được coi là khởi tạo khi hoàn thành quá trình khởi tạo của nó.

Và truy cập thành viên của đối tượng trước khi xây dựng không được phép bởi [basic.life]/(7.1).

+0

Tôi giả sử rằng bạn có nghĩa là truy cập vào 'f() :: s.value' là sai trong câu hỏi của tôi, tôi tin rằng gọi' main(): lh() 'sẽ hợp lệ nếu việc thực hiện chức năng này sẽ không chạm vào' f() :: s'? – PiotrNycz

+1

@PiotrNycz Đúng vậy. – Columbo

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