Почему я не могу сделать foo({"asd","asd1"}) с foo(char* args[])?

Я читаю C++ Primer и в разделе 6.2 он говорит:

"инициализация параметров работает так же, как и переменная инициализация."

но когда я это делаю:

void foo(char* args[]) {return;}

int main() {

char* args[]={"asd","dsa"};  // ok.

foo({"asd","dsa"});          // error.

}

почему это?

4 ответов


Как @ T. C. указал в комментариях, args в аргументе функции преобразуется в char**, потому что функции не могут принимать массивы в качестве аргумента. Так как вы не можете сделать

char **asd={"asd","dsa"}; 

кодекса является незаконным. Мое смущение было вызвано тем, что

char* args[]={"asd","dsa"};
char **asd=args;

является законным.


обычно можно воспользоваться новым синтаксисом инициализации и семантикой для использования анонимных массивов в качестве аргументов, но вам придется прыгать через несколько обручей. Например

typedef const char *CC2[2];

void foo(const CC2 &a) {}

int main() {
  foo({ "asd", "dsa" });
}

однако в вашем случае этот метод не поможет, потому что вы запрашиваете преобразование массива в указатель на временный массив. Это незаконно на C++.

typedef int A[2];

const A &r = A{ 1, 2 }; // reference binding is OK
int *p = A{ 1, 2 };     // ERROR: taking address is not OK

поэтому, если вы действительно хотите сделать что-то подобное, вы можете сделать после

template <size_t N> void foo(const char *const (&args)[N]) {}

int main() {
  foo({ "asd", "dsa" });
}

но это не совсем то, что вы изначально в виду.


"инициализация параметров работает так же, как и инициализация переменных."

Это касается как строителей, я думаю, они имеют в виду. Однако инициализаторы являются специальными и отличаются от обычных выражений значений, которые можно назначить переменной или передать вызову функции.

C / C++ не имеет способа написать литеральный анонимный массив. Вы можете сделать это только как инициализатор при объявлении переменной.


почему это?

прежде всего в обоих случаях вам нужно char const* потому что вы работаете со строковыми литералами.

во-вторых, {...} может работать, если тип параметра является массивом, но char*[] is скорректированная to char** (из-за decayment), который не может быть инициализирован с braced-init-list.


можно использовать std::string и std::vector, а вы уже должны do:

void foo(std::vector<std::string> args) {return;}

и:

foo({"asd","dsa"});

будет работать нормально.