Использование списка инициализации массива как временного в С++ 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". Результатом является указатель на первый элемент массива.
Ответы
Ответ 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.