2012-08-06 38 views
18

Tôi đã có một tình huống mà có thể được tóm tắt trong những điều sau đây:Khởi tạo một mảng có kích thước không đổi trong một danh sách initializer

class Test 
{ 

    Test(); 

    int MySet[10]; 

}; 

là nó có thể khởi tạo MySet trong một danh sách initializer?

Giống như loại danh sách initializer:

Test::Test() : MySet({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {} 

Có cách nào để khởi tạo một mảng thành viên liên tục cỡ trong danh sách initalizer của một lớp?

+3

Đối với giá trị, 'Đặt' không chỉ là con trỏ đến mảng các số nguyên '10', cũng không phải là' tĩnh' ở đây. Thay vào đó, tên mảng 'Set' phân rã thành con trỏ tới phần tử đầu tiên của mảng trong các tình huống nhất định. Sự khác biệt có thể được nhìn thấy rõ ràng bằng cách sử dụng 'sizeof' - tức là' sizeof (Set) == 10 * sizeof (int)! = Sizeof (int *) '. –

+1

@StuartGolodetz Cảm ơn bạn đã làm rõ. Khi tôi nói tĩnh, tôi có nghĩa là tĩnh trong các hình thức mà nó được lưu trữ với các đối tượng/dụ, và không chỉ ở một nơi khác trong heap. Tất nhiên, đó là một sự lạm dụng toàn bộ thuật ngữ 'tĩnh' trên một phần của tôi; lấy làm tiếc. – Serge

+0

Đừng lo lắng :) Tôi chủ yếu chỉ cố gắng làm rõ sự khác biệt giữa mảng và con trỏ trên cơ hội không có khả năng có một sự hiểu lầm ở đó. –

Trả lời

21

Trong khi không có sẵn trong C++ 03, C++ 11 giới thiệu danh sách khởi tạo mở rộng. Bạn thực sự có thể làm điều đó nếu sử dụng một trình biên dịch phù hợp với tiêu chuẩn C++ 11.

struct Test { 
    Test() : set { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } { }; 
    int set[10]; 
}; 

Mã trên biên dịch tiền phạt bằng cách sử dụng g++ -std=c++0x -c test.cc.


Như đã chỉ ra dưới đây cho tôi bởi một người dùng hữu ích trong các ý kiến, mã này không biên dịch sử dụng của Microsoft VC++ biên dịch, cl. Có lẽ ai đó có thể cho tôi biết nếu tương đương sử dụng std::array sẽ?

#include <array> 

struct Test { 
    Test() : set { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } } { }; 
    std::array<int, 10> set; 
}; 

Điều này cũng biên soạn tiền phạt bằng cách sử dụng g++ -std=c++0x -c test.cc.

+2

Một lý do khác để yêu C++ 11 (hoặc một số phần của nó)! = D Cảm ơn bạn rất nhiều! – Serge

+0

@Serge không có vấn đề gì! – oldrinb

+5

Lưu ý rằng mã này không biên dịch với Visual C++ phiên bản 11 và trước đó (tức là, nó không biên dịch với Microsoft Visual Studio 2012 và Visual C++ là trình biên dịch chính cho nền tảng phổ biến nhất). Vì vậy, ** nếu bạn muốn mã di động, đừng làm điều này **. Chưa. –

4

Thật không may, trong C++ 03, bạn không thể khởi tạo các mảng trong danh sách khởi tạo. Bạn có thể trong C++ 11 tuy nhiên nếu trình biên dịch của bạn là mới hơn :)

see: How do I initialize a member array with an initializer_list?

+1

Ngay cả C++ 98 cũng hỗ trợ zero-initialization của các mảng trong các danh sách khởi tạo. –

3

"Tôi hiểu rằng Set chỉ là một con trỏ đến mảng tĩnh của 10 số nguyên"

Không, đó là sai: nó là một mảng, không phải là một con trỏ.

Bạn vẫn có thể khởi tạo nó trong danh sách bộ khởi tạo của hàm tạo.

Đối với một trình biên dịch mà không hỗ trợ C++ 11 dấu ngoặc nhọn khởi (Visual C++ phiên bản 11 và trước đó nói đến cái tâm), bạn sẽ phải nhảy qua một số hoops mặc dù, như hình dưới đây:

#include <iostream> 
#include <vector> 
using namespace std; 

#define CPP11 
#if defined(_MSC_VER) 
# if (_MSC_VER <= 1700) 
#  undef CPP11 
# endif 
#endif 

#ifdef CPP11 
class Cpp11 
{ 
private: 
    int set_[10]; 

public: 
    Cpp11() 
     : set_{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } 
    {} 

    int foo() const { return set_[3]; } 
}; 
#endif 

class Cpp03 
{ 
private: 
    struct IntArray10 { int values[10]; }; 
    IntArray10 set_; 

    static IntArray10 const& oneToTen() 
    { 
     static IntArray10 const values = 
      { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} }; 
     return values; 
    } 

public: 
    Cpp03() 
     : set_(oneToTen()) 
    {} 

    int foo() const { return set_.values[3]; } 
}; 

int main() 
{} 

Thay vì sử dụng mảng thô, mặc dù, sử dụng std::vector và C+++ 11 std::array, cả hai đều được hỗ trợ ngay cả bằng Visual C++ 11.

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