Это действительный C ++? - PullRequest
       16

Это действительный C ++?

2 голосов
/ 31 октября 2009
struct SomeStruct
{
  int a; 
  int b;
};

SomeStruct someFn( int init )
{
  SomeStruct ret = { init, init };
  //...
  return ret;
}

void someFn2( SomeStruct* pStruct )
{
  // ..
}

int main( )
{
  someFn2( &someFn(32) );
  return 0;
}

Ответы [ 4 ]

19 голосов
/ 31 октября 2009

Нет, это недействительно.

Начиная с 5.2.2 / 10 [expr.call] "Вызов функции является lvalue тогда и только тогда, когда тип результата является ссылкой.

От 5.3.1 / 2 [expr.unary.op] "Операндом должно быть lvalue или квалифицированный идентификатор ".

Следовательно,

someFn(32) не является lvalue , поскольку SomeStruct не является ссылкой, и вы используете его в качестве операнда для &, который требует lvalue.

5 голосов
/ 31 октября 2009

Нет, это не так.

Вы можете использовать только & lvalues. SomeFn (32) не является lvalue.

Ваше главное должно быть так:

int main( )
{
  SomeStruct s;
  s = someFn(32);
  someFn2(&s);
  return 0;
}
5 голосов
/ 31 октября 2009
$ g++ -Wall -o stuct struct.cc 
struct.cc: In function ‘int main()’:
struct.cc:21: warning: taking address of temporary

Вы, вероятно, должны делать:

int main( )
{
  SomeStruct s = someFn(32);
  someFn2(&s);
  return 0;
}
2 голосов
/ 31 октября 2009

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

#include<iostream>

struct SomeStruct {
    int a;
    int b;

    ~SomeStruct() {
        std::cout << "SomeStruct destroyed" << std::endl;
    }
};

SomeStruct someFn ( int init )
{
    SomeStruct ret = { init, init };
    return ret;
}

void someFn2 ( SomeStruct* pStruct )
{
    std::cout << "someFn2 called" << std::endl;
}

void someFn2 ( const SomeStruct& someStruct )
{
    std::cout << "someFn2 called" << std::endl;
}

int main( )
{
    someFn2 ( &someFn ( 32 ) ); // warning - taking address of temporary
    someFn2 ( someFn ( 32 ) ); // no warning - safe in non-broken compilers
    return 0;
}

выходы

someFn2 called
SomeStruct destroyed
someFn2 called
SomeStruct destroyed

IIRC, набор «неразрушенных» компиляторов не включает Visual C ++ 2003 или более раннюю версию.

Примером этой идиомы в stl будет:

string a = "red";
string b = " apple";
string c = a + b;

где конструктор std::string(const std::string&) вызывается для c с временным std::string, возвращаемым из вызова std::string::operator+.

...