временный объект, параметры функции и неявное приведение - PullRequest
2 голосов
/ 21 июля 2009

В следующем сценарии:

struct Foo
{
   // ...
   operator Bar() {... }  // implicit cast to Bar
}

Foo GetFoo() { ... }
void CallMeBar(Bar x) { ... }

// ...
CallMeBar( GetFoo() );

[править] исправлен оператор приведения, д'Ох [/ править]

GetFoo возвращает временный объект типа Foo. Этот объект выживает до тех пор, пока не вернется CallMe? Что говорит стандарт?

Я понимаю, что если CallMe примет Foo, временный объект не будет уничтожен, пока не вернется CallMe. Однако я не уверен, что неявное приведение изменит это, и гарантированно выживет только временный Bar.


Типичным случаем будет Foo = CString, Bar = char *, т. Е. Бар, ссылающийся на данные, хранящиеся (и освобождаемые) Foo.

Ответы [ 4 ]

7 голосов
/ 21 июля 2009

Независимо от приведения временный объект (ы) «переживет» вызов функции CallMe() из-за стандарта C ++:

12.2.3 [...] Временные объекты уничтожаются как последний шаг в оценке фуллекс-выражения (1.9), которое (лексически) содержит точку, где они были созданы. [...]

1.9.12 A fullexpression - это выражение, которое не является подвыражением другого выражения.

2 голосов
/ 21 июля 2009

Он выживет, но полагаться на этот факт может сбить с толку, и это может привести к тому, что клиенты вашего кода достигнут стандарта C ++, зададут вопросы о переполнении стека и т.д .;-). Например, что происходит, когда кто-то делает:

Bar b = GetFoo();
CallMeBar(b);

На этот раз Foo прошел до вызова CallMeBar, но большинство программистов хотели бы, чтобы преобразования создавали независимый объект и, следовательно, чтобы код вел себя так же, как:

CallMeBar(GetFoo());

Вот почему std::string не имеет неявного приведения к char*, в отличие от CString приведения к LPCTSTR. Вместо этого std::string имеет функцию-член c_str(), которая имеет такое же ограничение, но делает несколько более очевидным при вызове кода, что это не реальное преобразование:

CallMePtr(GetString().c_str());   // OK

char* p = GetString().c_str();    // Bad
CallMePtr(p);                     // Badness manifests

const string &s = GetString();    // use "the most important const"
CallMePtr(s.c_str());             // Best be on the safe side
1 голос
/ 21 июля 2009

То, как я склонен думать об этом - магический персонаж - точка с запятой. Точка с запятой запускает деструкторы.

1 голос
/ 21 июля 2009

Пока вы возвращаете их по значению, они сохраняются до тех пор, пока CallMeBar не завершится.

Хотя ваш оператор приведения немного не работает.Должно быть:

struct Foo
{
   // ...
  operator Bar() {... }  // implicit cast to Bar
}

См. Например http://msdn.microsoft.com/en-us/library/ts48df3y(VS.80).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...