【问题标题】:Losing pointer reference outside scope在范围外丢失指针引用
【发布时间】:2017-09-30 23:56:56
【问题描述】:

首先,这是一个新手问题。我已经构建了一个基本的 c++ 包装类,用于在一个小项目的框架中与sqlite3 进行交互。这是其中的一部分:

data_wrapper.hpp

#ifndef DATAWRAPPER_H
#define DATAWRAPPER_H

class DataWrapper
{
private:
    sqlite3      *db_;
    const char   *db_file_;
    int          rc_;

    bool prepare ( sqlite3_stmt* statement, const char* query );
    bool check_table ( const char* table_name );

public:
    DataWrapper ( const char* db_file );
    sqlite3* get_database();
};

#endif // DATAWRAPPER_H

data_wrapper.cpp

#include <iostream>
#include <cstring>

#include "data_wrapper.hpp"

using namespace std;

DataWrapper::DataWrapper ( const char* db_file ) : db_ ( nullptr )
{
    db_file_ = db_file;
}

sqlite3* DataWrapper::get_database()
{
    return db_;
}

bool DataWrapper::prepare ( sqlite3_stmt* statement, const char* query )
{
    cout << "preparing: " << query << endl;
    rc_ = sqlite3_prepare_v2 ( db_, query, strlen ( query ), &statement, 0 );
    cout << "statement is: " << &statement << endl;

    return rc_ == SQLITE_OK;
}

/**
 * Checks if a given table is present on the database
 *
 * @param  table_name The name of the table to check.
 * @return bool       True if table exists, false otherwise.
 */
bool DataWrapper::check_table ( const char* table_name )
{
    const char* query = "SELECT name FROM sqlite_master WHERE type='table' AND name=?;";
    sqlite3_stmt* stmt = nullptr;

    if ( !prepare ( stmt, query ) ) {
        cout << "can't prepare query" << endl;

        return false;
    }

    cout << "statement now is: " << stmt << endl;

    if ( !bind ( stmt, 1, table_name ) ) {
        return false;
    }

    step ( stmt );

    return rc_ == SQLITE_ROW;
}

在某个地方,我有一个init 公共方法,它打开一个连接并检查给定表是否存在。专家会看到问题,可以通过控制台输出来总结:

preparing: SELECT name FROM sqlite_master WHERE type='table' AND name=?;
done preparing
statement is: 0x7fff6bd121d0
statement now is: 0

并不是说sqlite3 的使用是这里问题的一部分(或者是吗?),但当然,我不能在NULL 语句上绑定任何东西:

(21) API called with NULL prepared statement
(21) misuse at line 76880 of [a65a62893c]

prepare 作用域结束后,您会看到我丢失了指针引用。我一直在寻找类似问题的堆栈,但没有一个能正确解决我的问题。那么我怎样才能防止这种情况发生,并且可能现代, 在学习曲线上,我不妨掌握实际的 c++11 技术。

【问题讨论】:

  • cout &lt;&lt; "statement is: " &lt;&lt; &amp;statement &lt;&lt; endl; 打印指针statement 的地址,而不是它指向的地址。您可能想删除&amp;
  • 对不起,我真的尽力避免这种情况......
  • 其他小细节:您可能希望将db_file_ 设为std::string,否则如果我指向的内容超出范围,您将遇到麻烦。 (或者自己strcpy)。

标签: c++ c++11 pointers scope reference


【解决方案1】:

prepare签名应该是

bool DataWrapper::prepare ( sqlite3_stmt*& statement, const char* query ) 

注意为语句添加的&amp;。 当你传递指针参数时,你复制它的值(这是一个地址)。在函数内部更新此参数不会更改调用函数中的指针。 在更改函数以通过引用接收参数之前添加&amp;,这将在被调用函数内部进行任何更新以更新调用函数的参数。

【讨论】:

    【解决方案2】:
    bool DataWrapper::prepare ( sqlite3_stmt* statement, const char* query )
    

    上述函数按值获取statement 指针,因此当您将指针传递给这样的指针时:

    rc_ = sqlite3_prepare_v2 ( db_, query, strlen ( query ), &statement, 0 );
    

    您只是在更新本地副本,而不是调用站点上的副本。

    简单的解决方法是通过引用获取指针:

    bool DataWrapper::prepare ( sqlite3_stmt*& statement, const char* query )
    

    【讨论】:

      猜你喜欢
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      相关资源
      最近更新 更多