Ссылки на временные объекты (в случае sqlite++)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.07.08 09:49
Оценка:
Доброго дня!

Решил попользоваться SQLite++ (найденную благодоря RSDN) и наткнулся на некоторые особенности. В результате чего возникли, как я надеюсь, обоснованные подозрения. Поэтому и создал данную тему -- чтобы подозрения были либо доказаны, либо развеяны независимыми экспертами

Итак, SQLite++ позволяет связывать данные с запросом посредством конструкции use:
using namespace sqlitepp;

int b = ...;
statement st( session );
session << "select * from table where a = :b", use(b);
st.exec();


Подозрения связаны с ситуацией, когда в use передается временный объект. Например, есть у меня структура с методом-getter-ом:
class my_data_t {
  ...
  int age() const { return m_age; };
private :
  int m_age;
}

Вот такое формирование запроса в SQLite++ представляется мне ошибочным:
my_data_t data = ...;
statement st( session );
session << "select * from table where age > :age", use(data.age());
st.exec();

Поскольку в данном случае use_binder сохраняет ссылку на временный объект. Это можно видеть из исходного кода use_binder-а:
template<typename T>
class use_pos_binder_const : public use_binder
{
public:
    use_pos_binder_const(T const& value)
        : value_(value)
    {
    }
protected:
//В объекте хранится не копия, а ссылка!
    T const& value_;
private:
    void do_bind(statement& st, int pos)
...
};
...
//Похоже, что в случае use(data.age()) вызывается именно этот use.
template<typename T>
inline use_binder_ptr use(T const& t)
{
    return use_binder_ptr(new use_pos_binder_const<T>(t));
}


Получается, что при вызове data.age() возвращается временный объект. Задействуется use(T const&), который создает use_pos_binder_const, в котором сохраняется константная ссылка на временный объект. После завершения операторов << и , временный объект прекращает свою жизнь. Но ссылка на него остается в use_pos_binder_const. И используется в последующем вызове exec().

Обоснованы мои подозрения?
Если да, то SQLite++ придется использовать так:
my_data_t data = ...;
int age = data.age();
statement st( session );
session << "select * from table where age > :age", use(age);
st.exec();


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.