Методы цепочки и временные переменные, пожалуйста, уточните

Всем привет!

У меня есть класс, который получает указатель на «круг» (например), а затем настраивает его атрибуты с помощью некоторых методов «цепочки». Что-то вроде этого:

class CCircleSetter
{
public:
   explicit CCircleSetter( CCirclePtr circle ) : m_circle(circle)
   {
   }

   CCircleSetter & Radius( int radius )
   {
       if (m_circle) m_circle->SetAttribute( "radius", radius );
       return *this;
   }
   CCircleSetter & Center( CPoint center )
   {
       if (m_circle) m_circle->SetAttribute( "center", center );
       return *this;
   }

   operator bool() const
   {
      return ( m_circle != NULL );
   }

private:
   CCirclePtr m_circle;
};

Теперь мне интересно, является ли этот код законным или нет:

if ( CCircleSetter(myCircle).Radius(10).Center(myPoint) ) 
{ ... }

С одной стороны, я думаю, что временный объект, созданный внутри выражения "если", будет жить до конца этого выражения. Итак, звонки в «Радиус» и «Центр» законны. Но, с другой стороны, использование ссылок на временные переменные является неопределенным поведением, и мне кажется, что я делаю именно такие вещи - использую (*this), где "это" является временным. Это вызывает у меня некоторые сомнения, поэтому, пожалуйста, уточните. Спасибо!


person SadSido    schedule 09.08.2010    source источник
comment
Цепочка методов: возможно, это попытка создать свободный интерфейс?   -  person David    schedule 10.08.2010
comment
Спасибо за ссылку. Из Wiki: свободный интерфейс подразумевает больше, чем просто цепочку методов =)   -  person SadSido    schedule 10.08.2010


Ответы (4)


Нет, в этом очень конкретном случае это нормально, потому что временные файлы будут уничтожены ПОСЛЕ выполнения всей строки, но в целом очень плохо хранить ссылки на временные файлы.

person Dr. Snoopy    schedule 09.08.2010
comment
временное будет уничтожено ПОСЛЕ выполнения всей строки - это именно то, что я хотел услышать. Есть ссылки на стандарт? - person SadSido; 10.08.2010
comment
Ссылка на C++11 находится в главе 12.2 параграф 3: Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. - person Pixelchemist; 04.02.2014

Даже если это временная переменная, это не означает, что все ее члены временны. Внутри области вашего временного объекта указатель this и другие элементы не являются временными. Ваш код полностью в порядке. Теперь, если вы сделали что-то вроде:

SomeFunc(&CCircleSetter(myCircle))

это будет ссылка на временную переменную.

person tenfour    schedule 09.08.2010

Я не думаю, что ссылка на временное не определена, это просто запрещено. Кроме того, я считаю, что это относится только к аргументам функции. Visual Studio позволит вам передавать ссылки на неконстантные временные файлы на уровне предупреждений/ошибок по умолчанию, хотя я знаю, что gcc этого не сделает.

Насколько я знаю, это запрещено только для того, чтобы программисты не стреляли себе в ногу, сохраняя ссылку на временное, выходящее за рамки. Учитывая, что это C++, я нахожу это довольно глупым.

Я не вижу никакой проблемы в том, что ты делаешь.

person Collin Dauphinee    schedule 09.08.2010

То, что вы делаете, в основном то же самое, что и в

if( istrm >> a >> b ) ...

что то же самое, что

if( istream.operator>>(a).operator>>(b).operator some_bool_like_type() )

Я думаю, что это хорошо с точки зрения удобства использования. (Конечно, с этим нет никаких синтаксических/семантических проблем.)

Однако, как всегда, неявное преобразование в bool немного неприятно, потому что оно позволяет компилировать неожиданный код:

if ( CCircleSetter(myCircle).Radius(10) != 10 )
person sbi    schedule 09.08.2010
comment
да, то же самое. Но в этом примере istream не является переменной, созданной внутри выражения if - конструктор/деструктор для istream не вызывается. В этом был смысл моего вопроса. Что касается неожиданного кода: является ли (true != 10) допустимым выражением? - person SadSido; 10.08.2010
comment
@SadSido: bool неявно преобразуется в int, поэтому я думаю, что это должно скомпилироваться. Но даже если это не так, operator bool подлый зверь. Однажды я наткнулся на реализацию умного указателя, в которой создатели забыли перегрузить <. Когда ты засунул их в std::map, на помощь пришла его operator bool, и карта сравнила результаты этого. Пустой указатель был меньше непустого, и все непустые были одинаковыми. Таким образом, вы получили максимум 2 предмета на карте. Это заняло некоторое время для отладки, пока я не нашел недостающие операторы сравнения... - person sbi; 10.08.2010