Tôi có cái này struct
:
struct Snapshot
{
double x;
int y;
};
Tôi muốn x
và y
trở 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ì?
Tôi có cái này struct
:
struct Snapshot
{
double x;
int y;
};
Tôi muốn x
và y
trở 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ì?
Câu trả lời:
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.
Snapshot s = {};
làm việc cho các thành viên không phải POD (vì không có họ)?
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.
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
}
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();
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 foo
mà 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.
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 memset
hoặ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 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.
0
ở những nơi đó trong bộ nhớ. Điều này không giống như khởi tạo!
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 ++.
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());
}