Подтвердить что ты не робот

Использование списка инициализации массива как временного в С++ 11?

Я могу создать именованную переменную с массивом следующим образом:

char s[] = {1, 2, 3, 0};
if (strcmp(s, t))
    ...

Однако следующее не работает:

if (strcmp(char[]{1,2,3,0}, t))
    ...

Можно ли указать временный неназванный массив с списком инициализаторов? (В этом случае строковый литерал будет работать, но для массивов, отличных от char массивов?)

Update:

#include <iostream>
#include <cstring>

using namespace std;

typedef char CA[];

int main()
{
        cout << CA{1,2,3, 0} << endl;
}

дает error: taking address of temporary array (g++-4.7.2 -std=gnu++11)

Обновление 2:

Я думаю (возможно), что происходит в том, что строковые литералы особенно благословлены как lvalues, однако временные массивы являются prvalues, и поэтому вы не можете принять их адрес. Это, конечно, дикая догадка, но я не уверен.

Обновление 3:

Собственно, это должно быть неправильно, я думаю:

Значение lvalue или rvalue типа "массив N T" или "массив неизвестной границы T" можно преобразовать в prvalue типа "указатель на T". Результатом является указатель на первый элемент массива.

4b9b3361

Ответ 1

1) Я некоторое время страдала от этой проблемы. Компилируя следующую программу, g++ 4.7.1 (tdm64-1) дает ошибку: "teste1.cpp: 6: 33: ошибка: обращение к временному массиву"

#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char t[]={1,2,3,0};
  if (strcmp((char[]){1,2,3,0},t)==0)  //error
    cout << "equal\n";
  else 
    cout << "different\n";
}

Однако, если вы добавите ключевое слово "const" , ошибка исчезнет, ​​и программа будет работать гладко:

if (strcmp((const char[]){1,2,3,0},t)==0) //correct

2) В некоторых случаях просто добавить ключевое слово "const" может быть недостаточно. Например, g++ 4.7.1 дает "ошибку: принимая адрес временного массива" при компиляции следующей программы:

#include <iostream>
#include <cstring>
using namespace std;

void f(char* p)
{ for (int i=0; p[i]!=0; i++) 
    cout << int(p[i]) << " ";
  cout << endl;
}

int main() {
  f((char[]){1,2,3,0}); // error
}

Если вы добавите ключевое слово "const" , компилятор даст еще один вид ошибки: "неверное преобразование из" const char * "в" char * "[-fpermissive]":

f((const char[]){1,2,3,0}); //error

Чтобы успешно скомпилировать программу, вы можете скомпилировать ее с параметром "-fpermissive" или сделать явное преобразование типов:

f((char*)(const char[]){1,2,3,0}); // correct

Ответ 2

Да используйте typedef, а затем скажите

ArrayType{1, 2, 3, 0}

Альтернативно используйте шаблон псевдонима, а затем

AliasTemplate<char[]>{1, 2, 3, 0}

Ответ 3

Кажется, что эту проблему можно решить с помощью С++ 11 "move". Компиляция в g++ 4.8.1 программа:

#include <iostream>
#include <cstring>
using namespace std;

typedef char CA[];
int main() {
  cout << CA{'a','b','c',0} << endl;
}

приводит к ошибке: с адресом временного массива. Однако, используя "move":

cout << move(CA{'a','b','c',0}) << endl;

программа компилируется и работает правильно. Компилятор должен быть вызван для использования диалекта С++ 11:

g++ prog1.cpp -o prog.exe -std=c++11

Аналогично,

#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char t[]={1,2,3,0};
  if (strcmp( move((char[]){1,2,3,0}) ,t)==0)  //OK
    cout << "equal\n";
  else 
    cout << "different\n";
}

также компилируется и выполняется правильно, используя флаг -std = С++ 11.