Значения по умолчанию для аргументов массива - PullRequest
13 голосов
/ 17 августа 2011

Просто немного поиграюсь с C ++. Что я действительно хочу сделать, так это уметь настроить функцию со значениями по умолчанию, определенными для аргумента массива или указателя. Для простоты, давайте просто использовать массив. Вот так:

void experimentA(char a[3] = {'a', 'b', 'c'});

Компилятор (LLVM GCC 4.2 с GNU99) жалуется на "Ожидаемое выражение". Это довольно глупо, но мне сказали коллеги, что это происходит потому, что «значение», которое я пытаюсь присвоить, статически размещено, тогда как переменная, которую я пытаюсь присвоить (a[3]), является автоматической.

Но я не совсем уверен, так ли это, так как я могу сделать это:

void experimentB(char a[3] = "abc");

И компилятор просто предупреждает меня, что преобразование строкового литерала в символ * устарело.

Я не понимаю, как «abc» принципиально отличается от {'a', 'b', 'c'}, чтобы вызвать это несоответствие. Любое понимание очень ценится!

Ответы [ 6 ]

7 голосов
/ 17 августа 2011

Ваши коллеги ошибаются или, может быть, вы неправильно поняли.

Первый ключ к пониманию - это то, что вы не можете иметь массив в качестве параметра функции в C или C ++. Причины исторические. Поэтому, когда вы пишете void experimentA(char a[3] ...), компилятор автоматически преобразует его в указатель, т.е. void experimentA(char* a ...). Таким образом, реальный вопрос заключается в том, почему "abc" является подходящим значением по умолчанию для a, а { 'a', 'b', 'c' } - нет. Причина в том, что, как объясняет компилятор, "abc" является выражением, а { 'a', 'b', 'c' } - нет (его инициализатор). В C ++ есть места, где вы можете использовать инициализатор, а в некоторых - нет. Значение по умолчанию для параметра оказывается одним из тех мест, которые вы не можете.

4 голосов
/ 17 августа 2011

Когда вы используете строковый литерал «abc», он выделяется компилятором где-то в памяти, и указатель на его первый символ используется в качестве значения по умолчанию. Так что для компилятора код такой: void experimentA(char a[3] = 0x12345678);.

Во втором случае, литерал массива не выделяется компилятором в виде строки (что я видел бы как некоторую несогласованность в языке).

2 голосов
/ 17 августа 2011

"abc" является выражением .Он ведет себя как-то иначе, в отличие от всех других выражений, когда он используется для инициализации переменной типа array of char.

{'a','b','c'} - это не выражение, а initializer .Это допускается только синтаксически в определениях переменных.Там синтаксис допускает либо выражение, либо инициализатор без выражения, но это не означает, что инициализаторы можно использовать как выражения где-либо еще.

1 голос
/ 17 августа 2011

Параметр по умолчанию должен быть действительным.

Вы можете позвонить

е ( "а")

но никогда

F ({ 'а', 'б', 'с'});

«abc» фактически является адресом в памяти, а {'a', 'b', 'c'} означает инициализацию массива или структуры / класса.

1 голос
/ 17 августа 2011

"abc" является выражением, {'a', 'b', 'c'} является статическим инициализатором. Последнее допускается только в объявлениях переменных. По неизвестным мне причинам аргумент со значением по умолчанию имеет другое правило грамматики, которое не допускает статические инициализаторы.

Есть некоторые существенные изменения, когда статические инициализаторы разрешены в C ++ 0x, но я не уверен, как это повлияет на рассматриваемый случай.

0 голосов
/ 13 сентября 2016

Один простой способ сделать это - перегрузка простой старой функции.Например, ниже имитируется значение параметра по умолчанию для параметра формата, который имеет тип char *:

static string to_string(time_point<system_clock> time)
{
    return to_string(time, "%Y-%m-%d-%H-%M-%S");
}

static string to_string(time_point<system_clock> time, const char* format)
{
    time_t tt = system_clock::to_time_t(time);

    char str[1024];
    if (std::strftime(str, sizeof(str), format, std::localtime(&tt)))
        return string(str);
    else return string();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...