Як я можу оголосити та визначити кілька змінних в одному рядку за допомогою C ++?


173

Я завжди хочу, що якщо я оголошу ці три змінні, всі вони матимуть значення 0

int column, row, index = 0;

Але я знаходжу, що лише індекс дорівнює нулю, а інші - непотрібні, як 844553 та 2423445.

Як я можу ініціалізувати всі ці змінні до нуля, не оголошуючи кожну змінну в новому рядку?


36
Обережно з тими рядковими багатозмінними деклараціями. Простіше, ніж ви думаєте, оголосити вказівник int, а потім список регулярних цілих чисел ( int* a, b, c;не робить так, як це виглядає).
Кріс Еберл

4
Є лише три змінні, чувак, пиши =0для кожної у своїх визначеннях. І якщо ви дійсно хочете багато змінних, то спробуйте масив: int a[10]={0}ініціалізуйте кожну a[i]до 0 для вас.
Стэн

Компілятор не повинен дозволяти цій конструкції, якщо вона буде вести себе інакше, ніж те, що розумний програміст очікував би на це ... imho
cph2117

1
@ cph2117 Розумний програміст подумає: "Хм, цей синтаксис може означати пару різних речей залежно від того, як граматика пов'язує речі" , знайдіть Стандарт, щоб дізнатися, що є правдою, і продовжуйте це.
підкреслюй_d

Перестаньте це робити. Це просто робить код важче читати. Сенс написання коду мовою високого рівня полягає в тому, щоб спростити користувачеві читання.
Мартін Йорк

Відповіді:



162

Коли ви заявляєте:

int column, row, index = 0;

Тільки індекс встановлений на нуль.

Однак ви можете зробити наступне:

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

Але особисто я віддаю перевагу наступному, на що було зазначено.
На мій погляд, це більш читабельна форма.

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

або

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

3
Між останніми двома я вирішую, виходячи з того, чи повинні ці два значення дійсно бути однаковими ( bool previousInputValue, presentInputValue;) або якщо вони просто зараз є одним і тим же типом, але насправді це не потрібно ( uint8_t height, width;можливо, перетвориться на uint8_t height; uint16_t width;майбутнє і мало бути uint8_t height; uint8_t width;почати з).
altendky

Тому що написання uint8_t height; uint16_t width;замість цього uint8_t height, width;економить 10 символів у майбутньому. :-) Ви, звичайно, можете це робити, як завгодно. Просто переконайтеся, що ви легко читаєте. Тож остання форма є найбільш явною.
Метт

Остання форма, безумовно, є найбільш чіткою, коли вона вказала тип кожної змінної та дала зрозуміти, що кожна з них ініціалізована. Однак це не однозначно щодо того, чи очікується, що стовпець і рядок будуть однаковими чи ні. Можливо, ми б воліли явної чіткості int presentValue = 0; typeof(presentValue) previousValue = presentValue;, але я вважаю, що typeof()це нестандартне розширення GCC.
altendky

49

Як сказав @Josh, правильна відповідь:

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

Вам потрібно буде стежити за тим самим, що й за допомогою покажчиків. Це:

int* a, b, c;

Еквівалентний:

int *a;
int b;
int c;

34
Я ненавиджу цю вказівну річ, це не має сенсу. Зірочка є частиною типу, тому вона має стосуватися всіх них. Уявіть, як би це було unsigned long x, y;оголошено xяк, unsigned longале yяк просто unsignedтак unsigned int! Це точно так само! </rant>
Cam Jackson

6
Це має сенс. "int * a, b, c;"
Jeroen

7
@JeroenBollen Ну так, це має сенс, якщо ви пишете зірочки вказівника поруч із назвою змінної замість типу, але це саме по собі не має сенсу. Як я вже говорив вище, зірочка є частиною типу, а не частиною назви, тому вона повинна групуватися з типом!
Cam Jackson

11
З іншого боку, насправді має сенс, що * не обов'язково є частиною типу, як int *aзасобом, який *aпредставляє intзначення.
mdenton8

2
Справа вже зроблена, але просто додати до неї недійсність - це по суті відсутність типу, але ви все одно можете робити покажчики на неї. Таким чином, чому void* aбуде компілювати, а void *a, b, cне буде. Ця раціоналізація працює для мене.
Джош C

25

Якщо ви оголошуєте одну змінну / об'єкт на рядок, це не тільки вирішує цю проблему, але робить код більш зрозумілим і запобігає нерозумним помилкам при оголошенні покажчиків.

Щоб безпосередньо відповісти на ваше запитання, потрібно ініціалізувати кожну змінну до 0 явно. int a = 0, b = 0, c = 0;.


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

Зауважте, що ця форма також буде працювати з власними типами, особливо коли їх конструктори беруть більше одного аргументу.


2
і нині з рівномірною ініціалізацією (очікує C ++ 17, виправляючи це для auto...): колонка int { 0 } , рядок { 0 } , індекс { 0 } ;
підкреслюй__11


4

Можливі підходи:

  • Ініціалізуйте всі локальні змінні з нулем.
  • Мати масив memsetчи {0}масив.
  • Зробіть це глобальним чи статичним.
  • Помістіть їх в structі memsetчи є конструктор , який буде форматувати їх до нуля.

#define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data [ AR_SIZE ]; // Просто ідея.
Аджай

Вибачте, я мав на увазі, чому ви включили у свою відповідь рядок " Масив, memset чи {0} масив "?
Mateen Ulhaq

memset (Дані, 0, sizeof (Дані)); // Якщо це можна упакувати логічно.
Аджай

2

Я б не рекомендував цього, але якщо ви дійсно вважаєте, що це один рядок і пишеться лише 0 раз, ви також можете це зробити:

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

0

Як уже згадували інші, від C ++ 17 далі ви можете використовувати структуровані прив'язки для декількох змінних призначень.

У поєднанні з std::arrayі аргументів шаблону дедукції ми можемо написати функцію , яка присвоює значення довільного числа змінних , не повторюючи тип або значення .

#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

Коли ви оголошуєте змінну, не ініціалізуючи її, вибирається випадкове число з пам'яті і змінна ініціалізується до цього значення.


7
не зовсім. Компілятор вирішує "ця змінна буде за адресою xxx", все, що трапилося за адресою xxx, буде початковим значенням, якщо її встановлено на щось явно (шляхом ініціалізації або призначення)
pm100

3
@ pm100, хоча краще і правда для будь-якої тривіальної реалізації, яка не перешкоджає домаганням користувачів ... це все-таки спрощує ;-), оскільки використання неініціалізованої змінної є UB, тому теоретично все може статися, включаючи будь-який код використання цієї змінної просто позбавлене програми - що особливо ймовірно, коли відбувається оптимізація.
підкреслюй__11

1
значенням цієї змінної було б те, що було за адресою, яку вона отримала, тобто мотлох.
Педро Вернетті

@PedroVernetti Не має значення, що сталося за вказаною адресою до оголошення нової змінної та отримало ту саму адресу. Якщо користувач оголошує нову змінну, не ініціалізуючи її зі значенням, а потім читає змінну, перш ніж призначити їй значення, програма має невизначене поведінку. Це нескінченно гірше, ніж "випадковий" і "мотлох", і його просто потрібно уникати.
підкреслити_16
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.