Передача анонимной переменной по ссылке

Стандартные типы C++, такие как int или char, имеют ctors, поэтому вы можете иметь такие выражения, как:

int a = int(67); // create anonymous variable and assing it to variable a
int b(13);       // initialize variable b
int(77);         // create anonymous variable

Пользовательские типы (структуры или классы) могут делать то же самое:

struct STRUCT
{
  STRUCT(int a){}
};

STRUCT c = STRUCT(67);
STRUCT d(13);
STRUCT(77);

Вопрос: почему мы можем передать ссылочную анонимную структуру или экземпляр класса, но не можем передать стандартные типы?

struct STRUCT
{
  STRUCT(int a){}
};

void func1(int& i){}
void func2(STRUCT& s){}
void func3(int i){}
void func4(STRUCT s){}

void main()
{
  //func1(int(56));  // ERROR: C2664
  func2(STRUCT(65)); // OK: anonymous object is created then assigned to a reference
  func3(int(46));    // OK: anonymous int is created then assigned to a parameter
  func4(STRUCT(12)); // OK: anonymous object is created then assigned to a parameter
}

person Ivars    schedule 09.11.2013    source источник
comment
Ваша строка func2 не должна компилироваться (по той же причине, что и первая).   -  person Mat    schedule 09.11.2013
comment
void main() нестандартен.   -  person n. 1.8e9-where's-my-share m.    schedule 09.11.2013
comment
При соответствующем уровне предупреждения вы получите warning C4239: nonstandard extension used : 'argument' : conversion from 'STRUCT' to 'STRUCT &'; A non-const reference may only be bound to an lvalue. Вы должны использовать /W4.   -  person n. 1.8e9-where's-my-share m.    schedule 09.11.2013
comment
@н.м. Может надо говорить нестандартные для таких вещей, это заблуждение. C++/CLI нестандартен. void main неправильно.   -  person Konrad Rudolph    schedule 09.11.2013
comment
@н.м. это просто говорит о том, насколько хорошо рассматриваемый код был протестирован на соответствие стандарту С++ :)   -  person BЈовић    schedule 09.11.2013
comment
Благодарность! но не означает, что void main() просто означает, что программа не возвращает значение в вызывающую среду и вместо этого будет действовать как процедура.   -  person Ivars    schedule 09.11.2013
comment
Стандарт говорит it shall have a return type of type int. Здесь не так много свободы.   -  person n. 1.8e9-where's-my-share m.    schedule 10.11.2013


Ответы (3)


Если ваш компилятор позволяет это, то это не стандартный совместимый компилятор C++. Вы не можете привязать временное rvalue к неконстантной ссылке lvalue. Это правило. И clang, и gcc не компилируйте этот код для func2(STRUCT(65));.

Вместо этого у вас есть альтернативы:

void func1(int&& i){}

void func1(const int& i){}

Унаследованное от С++ 03: ссылка (lvalue) на неконстантный тип (int &i), который должен иметь возможность изменять параметр, а затем передача временного объекта, такого как 56, нелогична, поскольку он не может быть изменен. Ссылка на константный тип (const int &i), который должен просто наблюдать значение как доступное только для чтения, тогда передача временного значения, такого как 52, допустима.

В С++ 11 вы можете ссылаться на неконстантный временный объект с помощью &&.

person masoud    schedule 09.11.2013

Похоже, вы используете компилятор MS VC++, в котором есть такая ошибка. :) Вы должны связать временный объект с константной ссылкой. Например, вы можете написать

const int &ri = 10;

но можно не писать

int &ri = 10;

То же самое относится и к пользовательским типам.

const STRUCT &rs = STRUCT( 10 );

STRUCT &rs = STRUCT( 10 ); // the compiler shall issue an error.
person Vlad from Moscow    schedule 09.11.2013

В С++ анонимный временный объект всегда является правильным значением. Чтобы принять правильное значение в качестве аргумента, вы можете:

1).void foo1 (ТИП); //передача по значению
2).void foo2(const TYPE &); //передача по константной ссылке
3).void foo3(TYPE &&); // в С++ 11 передача по ссылке на правое значение

Ваши «func3» и «func4» принимают аргумент, который передается по значению, это нормально.
Однако «func1» и «func2» могут принимать только аргумент, который передается по ссылке с левым значением. анонимный параметр.

person evensong    schedule 09.11.2013