Làm cách nào để khai báo và định nghĩa nhiều biến trong một dòng bằng C ++?


172

Tôi luôn luôn rằng nếu tôi khai báo ba biến này thì tất cả chúng sẽ có giá trị 0

int column, row, index = 0;

Nhưng tôi thấy rằng chỉ có chỉ số bằng 0 và những chỉ số khác là rác như 844553 & 2423445.

Làm thế nào tôi có thể khởi tạo tất cả các biến này thành 0 mà không cần khai báo từng biến trên một dòng mới?


36
Cẩn thận với các khai báo đa biến một dòng. Thật dễ dàng hơn bạn nghĩ để khai báo một con trỏ int theo sau là một danh sách các số nguyên thông thường ( int* a, b, c;không làm như vậy).
Chris Eberle

4
Chỉ có ba biến, anh chàng, viết =0cho mỗi một trong định nghĩa của họ. Và, nếu bạn thực sự muốn có nhiều biến, thì hãy thử một mảng: int a[10]={0}sẽ khởi tạo từng biến a[i]thành 0 cho bạn.
Stan

Trình biên dịch không nên cho phép cấu trúc đó nếu nó hoạt động khác với những gì một lập trình viên hợp lý mong đợi nó sẽ làm ...
imho

1
@ cph2117 Một lập trình viên hợp lý sẽ nghĩ 'hmm, cú pháp này có thể có nghĩa là một vài điều khác nhau tùy thuộc vào cách ngữ pháp liên kết mọi thứ' , tìm kiếm Tiêu chuẩn để tìm ra điều gì là đúng và tiếp tục với nó.
gạch dưới

Dừng làm việc này. Nó chỉ làm cho mã khó đọc hơn. Điểm của việc viết mã bằng một ngôn ngữ cấp cao là làm cho nó dễ dàng cho người bảo trì đọc.
Martin York

Câu trả lời:



161

Khi bạn tuyên bố:

int column, row, index = 0;

Chỉ mục được đặt thành không.

Tuy nhiên, bạn có thể làm như sau:

int column, row, index;
column = index = row = 0;

Nhưng cá nhân tôi thích những điều sau đây đã được chỉ ra.
Đó là một hình thức dễ đọc hơn trong quan điểm của tôi.

int column = 0, row = 0, index = 0;

hoặc là

int column = 0;
int row = 0;
int index = 0;

3
Giữa hai giá trị cuối cùng, tôi quyết định dựa trên việc hai giá trị đó có thực sự là cùng một loại ( bool previousInputValue, presentInputValue;) hay bây giờ chúng có phải là cùng một loại hay không nhưng thực sự cần phải có ( uint8_t height, width;có thể biến thành uint8_t height; uint16_t width;trong tương lai và nên có uint8_t height; uint8_t width;đầu tiên là).
altendky

Bởi vì viết uint8_t height; uint16_t width;thay vì uint8_t height, width;tiết kiệm 10 ký tự trong tương lai. :-) tất nhiên bạn có thể làm điều đó theo cách bạn muốn. Chỉ cần chắc chắn rằng bạn làm cho nó dễ dàng đọc. Vì vậy, hình thức cuối cùng là rõ ràng nhất.
Matt

Hình thức cuối cùng chắc chắn là rõ ràng nhất trong việc nêu rõ loại của từng biến và làm rõ rằng mỗi biến được khởi tạo. Điều đó nói rằng, không rõ ràng về việc liệu cột và hàng có được dự kiến ​​là cùng loại hay không. Có lẽ cả hai chúng tôi đều thích nhân chứng int presentValue = 0; typeof(presentValue) previousValue = presentValue;, nhưng tôi tin rằng đó typeof()là một phần mở rộng GCC không chuẩn.
altendky

49

Như @Josh đã nói, câu trả lời đúng là:

int column = 0,
    row = 0,
    index = 0;

Bạn sẽ cần coi chừng điều tương tự với con trỏ. Điều này:

int* a, b, c;

Tương đương với:

int *a;
int b;
int c;

34
Tôi ghét điều con trỏ, nó không có ý nghĩa. Dấu hoa thị là một phần của loại, vì vậy nó nên áp dụng cho tất cả chúng. Hãy tưởng tượng nếu unsigned long x, y;tuyên bố xnhư unsigned longnhưng ychỉ là unsigned, aka unsigned int! Điều đó giống hệt nhau! </ rant>
Cam Jackson

6
Nó có ý nghĩa. "int * a, b, c;"
Jeroen

7
@JeroenBollen Vâng, thật có ý nghĩa nếu bạn viết dấu hoa thị con trỏ bên cạnh tên biến thay vì loại, nhưng bản thân nó không có ý nghĩa gì. Giống như tôi đã nói ở trên, dấu hoa thị là một phần của loại, không phải là một phần của tên, vì vậy nó nên được nhóm với loại!
Cam Jackson

11
Về mặt không, thực tế nó có nghĩa là * không nhất thiết phải là một phần của loại, vì nó int *acó nghĩa là *ađại diện cho một intgiá trị.
mdenton8

2
Điểm đã được thực hiện nhưng chỉ cần thêm vào nó khoảng trống về cơ bản là thiếu một loại nhưng bạn vẫn có thể tạo con trỏ cho nó. Vì vậy, tại sao void* asẽ biên dịch và void *a, b, csẽ không. Sự hợp lý hóa này làm việc cho tôi.
Josh C

24

Nếu bạn khai báo một biến / đối tượng trên mỗi dòng không chỉ giải quyết vấn đề này mà còn làm cho mã rõ ràng hơn và ngăn ngừa các lỗi ngớ ngẩn khi khai báo con trỏ.

Để trả lời trực tiếp câu hỏi của bạn, bạn phải khởi tạo từng biến thành 0 một cách rõ ràng. int a = 0, b = 0, c = 0;.


16
int column(0), row(0), index(0);

Lưu ý rằng biểu mẫu này cũng sẽ hoạt động với các loại tùy chỉnh, đặc biệt là khi các hàm tạo của chúng có nhiều hơn một đối số.


2
và ngày nay với việc khởi tạo thống nhất (đang chờ C ++ 17 sửa lỗi này cho auto...): int cột { 0 } , hàng { 0 } , chỉ mục { 0 } ;
underscore_d

5

Kể từ 2k18, bạn có thể sử dụng Ràng buộccấu trúc :

#include <iostream>
#include <tuple>

int main () 
{
    auto [hello, world] = std::make_tuple("Hello ", "world!");
    std::cout << hello << world << std::endl;
    return 0;
}

Demo


4

Cách tiếp cận có thể:

  • Khởi tạo tất cả các biến cục bộ bằng không.
  • Có một mảng, memsethoặc {0}mảng.
  • Làm cho nó toàn cầu hoặc tĩnh.
  • Đặt chúng vào structmemsethoặc có một hàm tạo sẽ khởi tạo chúng về 0.

#define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Dữ liệu [ AR_SIZE ]; // Chỉ là một ý tưởng.
Ajay

Xin lỗi, ý tôi là, tại sao bạn lại đưa dòng " Có một mảng, bộ nhớ hoặc {0} mảng. " Trong câu trả lời của bạn?
Mateen Ulhaq

bộ nhớ (Dữ liệu, 0, sizeof (Dữ liệu)); // Nếu điều này có thể được đóng gói hợp lý.
Ajay

2

Tôi không khuyến nghị điều này, nhưng nếu bạn thực sự thích nó là một dòng và chỉ viết 0 một lần, bạn cũng có thể làm điều này:

int row, column, index = row = column = 0;

0

Như những người khác đã đề cập, từ C ++ 17 trở đi, bạn có thể sử dụng các ràng buộc có cấu trúc cho nhiều bài tập biến.

Kết hợp điều này với std::arraykhấu trừ đối số khuôn mẫu, chúng ta có thể viết một hàm gán giá trị cho một số biến tùy ý mà không lặp lại kiểu hoặc giá trị .

#include <iostream>
#include <array>

template <int N, typename T> auto assign(T value)
{
    std::array<T, N> out;
    out.fill(value);
    return out;
}

int main()
{
    auto [a, b, c] = assign<3>(1);

    for (const auto& v : {a, b, c})
    {
        std::cout << v << std::endl;
    }

    return 0;
}

Demo


-13

Khi bạn khai báo một biến mà không khởi tạo nó, một số ngẫu nhiên từ bộ nhớ được chọn và biến được khởi tạo cho giá trị đó.


7
không hẳn Trình biên dịch quyết định 'biến này sẽ ở địa chỉ xxx', bất cứ điều gì xảy ra ở địa chỉ xxx sẽ là giá trị ban đầu trừ khi nó được đặt thành một cái gì đó rõ ràng (bằng cách khởi tạo hoặc gán)
pm100

3
@ pm100 mặc dù tốt hơn và đúng với bất kỳ triển khai tầm thường nào không theo cách quấy rối người dùng ... điều đó vẫn quá đơn giản ;-) vì sử dụng một biến chưa được khởi tạo là UB, vì vậy về mặt lý thuyết, mọi thứ đều có thể xảy ra, kể cả bất kỳ mã nào sử dụng biến đó chỉ đơn giản là bị loại khỏi chương trình - điều này đặc biệt có khả năng khi tối ưu hóa đang diễn ra.
gạch dưới

1
giá trị của biến đó sẽ là bất cứ thứ gì có tại địa chỉ mà nó nhận được, tức là rác.
Pedro Vernetti

@PedroVernetti Không có vấn đề gì xảy ra tại địa chỉ nói trước khi biến mới được khai báo và tình cờ nhận được cùng một địa chỉ. Nếu người dùng khai báo biến mới mà không khởi tạo nó với một giá trị, sau đó đọc biến đó trước khi gán cho nó một giá trị, chương trình có hành vi không xác định. Điều đó vô cùng tồi tệ hơn "ngẫu nhiên" và "rác" và chỉ cần tránh.
gạch dưới
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.