2016-11-23 29 views
7

Tôi có hai kiểu khởi tạo biến cấu trúc trong mã của tôi.Có sự khác biệt nào giữa struct Data d = {0} và struct Data d = {}

Ví dụ

#include<iostream> 
#include<string> 
using namespace std; 
struct Data{ 
    int arr[5]; 
    float x; 

}; 
int main(){ 
    struct Data d = {0}; 
    struct Data d1 = {}; 
    cout<<d.arr[0]<<d.x; 
    cout<<d1.arr[0]<<d1.x<<endl; 
    return 0; 
} 

Tôi đang chạy quảng cáo đang nhận được 0 0 0 0 như đầu ra của tôi. Xin hãy giúp tôi, là có bất kỳ sự khác biệt giữa cả hai khởi tạo.

+0

Một danh sách khởi tạo mà bạn có bằng nhau chỉ là một danh sách khởi tạo rỗng. –

+0

Và bạn mong đợi điều gì trong mỗi? Bạn không nên khởi tạo cấu trúc của bạn như thế. Bạn cần phải truy cập vào mỗi thứ bên trong struct của bạn và khởi tạo nó. Có lẽ có một hàm có cấu trúc và có vòng lặp for để khởi tạo mọi thứ trong mảng của bạn thành 0 và x của bạn thành 0 –

+0

@Danh không bị giật. gắn thẻ một câu hỏi là 'c' vì nó liên quan đến cú pháp chung với c và C++ là không đúng nhưng nó không phải là" spam ". – djechlin

Trả lời

7

Theo quy tắc aggregate initialization, hiệu quả giống nhau ở đây, tức là tất cả các thành viên của cấu trúc sẽ là value-initialized (zero-initialized ở đây đối với loại không phải lớp).

Nếu số điều khoản initializer là ít hơn số lượng thành viên and bases (since C++17) hoặc danh sách khởi tạo là hoàn toàn trống rỗng, các thành viên còn lại and bases (since C++17) được khởi tạo by their default initializers, if provided in the class definition, and otherwise (since C++14) bởi danh sách rỗng, phù hợp với các quy tắc list-khởi tạo thông thường (mà thực hiện khởi tạo giá trị cho các loại không thuộc lớp và các lớp không tổng hợp với các hàm tạo mặc định và tổng hợp khởi tạo cho các tập hợp). Nếu một thành viên của một kiểu tham chiếu là một trong những thành viên còn lại, thì chương trình đó không đúng định dạng.

Chính xác hơn,

struct Data d = {0}; // initialize the 1st member of Data to 0, value-initialize(zero-initialize) the remaining members 
struct Data d1 = {}; // value-initialize(zero-initialize) all the members of Data 

Lưu ý rằng toàn bộ câu chuyện được dựa trên Data đó là một aggregate type và các thành viên của nó là loại phi lớp, nếu không hành vi sẽ thay đổi theo quy tắc của list initialization.

+1

Tôi nghĩ rằng nó đáng nói đến hiệu ứng khi 'Dữ liệu' có hàm tạo – Danh

+1

Cũng sẽ có sự khác biệt nếu thành viên đầu tiên của 'Dữ liệu' là loại lớp –

-2

Có, có sự khác biệt. Trong trường hợp đầu tiên, bạn đang khởi tạo rõ ràng thành viên đầu tiên của Data (arr[0]) về 0. Trong trường hợp thứ hai bạn không khởi tạo bất cứ điều gì và chỉ cần đọc bất cứ giá trị nào xảy ra ở đó. Trong trường hợp này, nó cũng bằng không, nhưng điều đó không được đảm bảo để hoạt động, đặc biệt là trong một chương trình phức tạp hơn.

Luôn luôn là ý tưởng tốt để khởi tạo tất cả các thành viên của cấu trúc. Xem xét phiên bản này sửa đổi một chút về chương trình của bạn mà nên làm những gì đang xảy ra rõ ràng:

#include<iostream> 
#include<string> 
using namespace std; 
struct Data{ 
    int arr[5]; 
    float x; 
}; 
int main(){ 
    struct Data d = {1, 2, 3, 4, 5, 3.14f}; 
    struct Data d1 = {}; 
    cout<<d.arr[0]<<", "<<d.x<<", "; 
    cout<<d1.arr[0]<<", "<<d1.x<<endl; 
    return 0; 
} 

này sẽ in:

1, 3.14, 0, 0 
+0

Chương trình của bạn cần minh họa điều gì? –

0

Việc khởi mặc định sử dụng {} được định nghĩa là khởi tạo của mỗi thành viên bằng cách sử dụng {}. Vì vậy, bằng cách làm

struct Data d1 = {}; 

Data d1 được khởi tạo để {{},{}}, đó là {{0, 0, 0, 0, 0}, 0.0},

như 00.0 là những giá trị mặc định cho intfloat resp.

Đây là lý do bạn không thấy bất kỳ sự khác biệt nào. Cả hai người trong số họ luôn làm điều tương tự trong trường hợp của bạn.

Sự khác biệt nằm trong những trường hợp:

1.) Đây là thời điểm cung cấp initializer bên {} trở thành bắt buộc:

struct X { 
    X(int); 
}; 

X x1 {}; // error : empty initializer. X(int) states that an int is required to construct an X. 
X x2 {0}; // OK 

2.) Kịch bản khi không khởi tạo được cấm:

struct Test { 
    string name; 
    int year; 
}; 
Test alpha0{0}; // Error. Because name in Test fails at zero-initialization. 
Test alpha{};  // OK. Because name in Test is default-initialized with empty string "". 
0

Kết quả là giống nhau trong trường hợp này, nhưng không nhất thiết phải như vậy trong các trường hợp khác.

Trong trường hợp này, bạn chưa cung cấp ctor, vì vậy bạn đang sử dụng tổng hợp khởi tạo. Điều này cho phép zero-initialization cho rỗng-init-list, và bạn đang cung cấp 0 cho cái trống rỗng, vì vậy cả hai làm việc giống nhau.

Nếu bạn cung cấp một ctor, nó sẽ là tầm thường để có được kết quả khác nhau từ hai:

#include <iostream> 

struct foo { 
    int f; 

    foo(int f = 5) : f(f) {} 
    friend std::ostream &operator<<(std::ostream &os, foo const &f) { 
     return os << f.f; 
    } 
}; 

int main() { 

    foo f1{}; 
    foo f2{0}; 

    std::cout << "Empty init list: " << f1 << "\n"; 
    std::cout << "zero init list: " << f2 << "\n"; 
} 

Mặc dù một ctor là cách rõ ràng nhất để làm điều này, nó không phải là người duy nhất. Để có một ví dụ rõ ràng khác (C++ 11 và mới hơn):

struct foo { 
    int f = 5; 
}; 
Các vấn đề liên quan