我遇到了一个对我没有多大意义的编译器错误:
#include <memory>
using namespace std;
auto_ptr<Table> table = db->query("select * from t");
错误:从'Table *'转换为非标量类型'std :: auto_ptr&lt;表&gt;”请求的
但是,以下行确实有效:
auto_ptr<Table> table(db->query("select * from t"));
构造函数的这个定义是什么阻止它像我期望的那样工作?我认为初始化的声明使用了构造函数。
这是我auto_ptr
的构造函数(来自SGI STL):
explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
答案 0 :(得分:17)
这是“明确的”关键字。
template <typename T>
struct foo
{
explicit foo(T const *)
{
}
};
template <typename T>
struct bar
{
bar(T const *)
{
}
};
int main(int argc, char **argv)
{
int a;
foo<int> f = &a; // doesn't work
bar<int> b = &a; // works
}
“explicit”关键字阻止构造函数用于隐式类型转换。考虑以下两个函数原型:
void baz(foo<int> const &);
void quux(bar<int> const &);
使用这些定义,尝试使用int指针调用这两个函数:
baz(&a); // fails
quux(&a); // succeeds
在quux的情况下,你的int指针被隐式转换为一个条。
编辑:要扩展其他人评论的内容,请考虑以下(相当愚蠢)代码:
void bar(std::auto_ptr<int>);
int main(int argc, char **argv)
{
bar(new int()); // probably what you want.
int a;
bar(&a); // ouch. auto_ptr would try to delete a at the end of the
// parameter's scope
int * b = new int();
bar(b);
*b = 42; // more subtle version of the above.
}
答案 1 :(得分:8)
您需要使用
auto_ptr<Table> table = auto_ptr<Table>(db->query("select * from t"));
auto_ptr没有为其模板类型定义赋值运算符。唯一允许的赋值来自另一个auto_ptr(它的指针构造函数是显式的)。这样做是为了保护auto_ptr的意外滥用,因为auto_ptr假设了内存的所有权。
我的猜测是你需要使用赋值表单来使用多个查询,如:
// initialize using constructor
auto_ptr<Table> table(db->query("select * from t1"));
...
// new query using assignment
table = auto_ptr<Table>(db->query("select * from t2"));
...
// another query using assignment
table = auto_ptr<Table>(db->query("select * from t3"));
答案 2 :(得分:5)
构造函数声明为显式,这意味着它不会用于隐式类型转换。由于auto_ptr占用了指针,因此隐式转换为auto_ptr很容易导致不良情况。
例如,如果auto_ptr允许从指针进行隐式转换,并且您意外地将指针传递给采用auto_ptr的方法,则指针将被静默转换为auto_ptr,并在函数结束时随后被删除,即使这不是意向。但是通过将构造函数标记为显式转换不能再以静默方式发生,并且通过调用构造函数,您可以清楚地表达将所有权传递给auto_ptr的意图,从而避免任何潜在的混淆。
void fun(std::auto_ptr<Foo> foo) // Assume implicit conversion is allowed.
{
// do stuff with foo
}
Foo *foo = new Foo();
f(foo); // Normally this isn't allowed.
foo->bar(); // Oops
答案 3 :(得分:2)
添加到lothar所说的内容:因为auto_ptr
构造函数是使用explicit
关键字声明的,所以需要使用explict强制转换来从原始指针创建auto_ptr
。 (在引入explicit
之前,隐式转换是许多新的 - 经验丰富的)C ++开发人员的祸根。)