Các thành viên của cấu trúc C ++ được khởi tạo thành 0 theo mặc định?


200

Tôi có cái này struct:

struct Snapshot
{
    double x; 
    int y;
};

Tôi muốn xytrở thành 0. Họ sẽ là 0 theo mặc định hay tôi phải làm:

Snapshot s = {0,0};

Các cách khác để loại bỏ cấu trúc là gì?


Sử dụng std :: map <> và trả về 0 khi khóa không tồn tại.
Jonny

Câu trả lời:


263

Chúng không null nếu bạn không khởi tạo cấu trúc.

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

Cái thứ hai sẽ làm cho tất cả các thành viên bằng không, cái đầu tiên để chúng ở các giá trị không xác định. Lưu ý rằng nó là đệ quy:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

Thứ hai sẽ làm cho p.s.{x,y}số không. Bạn không thể sử dụng các danh sách trình khởi tạo tổng hợp này nếu bạn có các hàm tạo trong cấu trúc của mình. Nếu đó là trường hợp, bạn sẽ phải thêm initalization thích hợp cho những người xây dựng

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

Sẽ khởi tạo cả x và y thành 0. Lưu ý rằng bạn có thể sử dụng x(), y()để khởi tạo chúng không quan tâm đến loại của chúng: Đó là khởi tạo giá trị và thường mang lại một giá trị ban đầu thích hợp (0 cho int, 0.0 cho double, gọi hàm tạo mặc định cho người dùng xác định loại có người xây dựng khai báo, ...). Điều này đặc biệt quan trọng nếu cấu trúc của bạn là một mẫu.


1
Điều này tạo ra rất nhiều cảnh báo trong trình biên dịch của tôi.
River-Claire Williamson

1
Roger: Hãy thử sử dụng struct có tên trong trình khởi tạo, đó là những gì tôi làm và tôi không nhận được bất kỳ cảnh báo nào trong VC 2012: Snapshot s = Snapshot ();
Kit10

@Johannes Schaub - litb Sẽ Snapshot s = {};làm việc cho các thành viên không phải POD (vì không có họ)?
ontherocks

2
C ++ 11 hiện cho phép bạn khởi tạo chúng theo định nghĩa của struct hoặc class, như vậy: struct Snapshot {double x {0}; // với dấu ngoặc int y = 0; // hoặc chỉ là kiểu trường học cũ 'bằng cách gán' cũng thực sự là khởi tạo};
ikku100

1
Là "Ảnh chụp s = {};" một phần của tiêu chuẩn?
Stefan

40

Không, chúng không phải là 0 theo mặc định. Cách đơn giản nhất để đảm bảo rằng tất cả các giá trị hoặc được mặc định là 0 là xác định hàm tạo

Snapshot() : x(0), y(0) {
}

Điều này đảm bảo rằng tất cả các sử dụng Snapshot sẽ có các giá trị khởi tạo.


24
Nhược điểm là struct không còn là kiểu POD, vì nó có hàm tạo. Điều đó sẽ phá vỡ một số hoạt động như ghi nó vào một tập tin tạm thời.
Finnw

16
@finnw: C ++ 11 sửa lỗi này, mặc dù struct không phải là POD, nhưng nó là "bố cục tiêu chuẩn".
Ben Voigt

19

Nói chung, không. Tuy nhiên, một cấu trúc được khai báo là phạm vi tệp hoặc tĩnh trong hàm / will / được khởi tạo thành 0 (giống như tất cả các biến khác của các phạm vi đó):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
Đó thực sự không phải là một giả định an toàn. bạn không nên dựa vào giá trị của bất cứ thứ gì bạn không khởi tạo
Hasturkun

24
Các đối tượng thời lượng lưu trữ tĩnh luôn được khởi tạo về 0 - xem stackoverflow.com/questions/60653/NH để biết trích dẫn từ tiêu chuẩn. Cho dù đây là phong cách tốt là một vấn đề khác.
bdonlan

12

Với POD bạn cũng có thể viết

Snapshot s = {};

Bạn không nên sử dụng bộ nhớ trong C ++, bộ nhớ có một nhược điểm là nếu không có POD trong cấu trúc thì nó sẽ phá hủy nó.

hoặc như thế này:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

@LightnessRacesinOrbit oh wat?
Ben Sinclair

@Andy Hầu hết gây nhiều tranh cãi Parse biến những điều mà nhìn như ctors bình thường - SomeType foo();là một điển hình, mặc dù nó có thể xảy ra với những người khác - vào định nghĩa hàm (trong trường hợp đó, một chức năng foomà lợi nhuận SomeType). Xin lỗi vì đã bị hoại tử, nhưng nếu có ai khác vấp phải điều này, tôi đã tìm ra câu trả lời.
Vụ kiện của Quỹ Monica

7

Trong C ++, sử dụng các hàm tạo không có đối số. Trong C, bạn không thể có các hàm tạo, vì vậy hãy sử dụng memsethoặc - giải pháp thú vị - các công cụ khởi tạo được chỉ định:

struct Snapshot s = { .x = 0.0, .y = 0.0 };

Tôi tin rằng đây là C, không phải C ++. Nó sẽ không biên dịch được dưới một số trình biên dịch C ++. Tôi đã trải nghiệm thất bại biên dịch theo Cygwin hoặc MinGW.
jww

3

Tôi tin rằng câu trả lời đúng là giá trị của chúng không được xác định. Thông thường, chúng được khởi tạo thành 0 khi chạy các phiên bản gỡ lỗi của mã. Điều này thường không phải là trường hợp khi chạy phiên bản phát hành.


2
Trên thực tế, các phiên bản gỡ lỗi chỉ xảy ra 0ở những nơi đó trong bộ nhớ. Điều này không giống như khởi tạo!
Các cuộc đua nhẹ nhàng trong quỹ đạo

3

Vì đây là POD (về cơ bản là cấu trúc C) nên có rất ít tác hại khi khởi tạo nó theo cách C:

Snapshot s;
memset(&s, 0, sizeof (s));

hoặc tương tự

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

Tôi sẽ không đi xa để sử dụng calloc()trong một chương trình C ++.


3
Giữ cho đôi; all-bits-zero không nhất thiết phải là 0,0. Tuy nhiên, bạn có thể kiểm tra xem bạn có nhân đôi IEEE754 hay không, trong trường hợp đó nó phải hoạt động.
MSalters

1

Di chuyển các thành viên nhóm đến một lớp cơ sở để rút ngắn danh sách trình khởi tạo của bạn:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.