Fra*_*ger 9 c++ gcc stl auto-ptr
我遇到了一个对我没有多大意义的编译器错误:
#include <memory>
using namespace std;
auto_ptr<Table> table = db->query("select * from t");
Run Code Online (Sandbox Code Playgroud)
错误:从'Table*'转换为非标量类型'std :: auto_ptr <Table>'
但是,以下行确实有效:
auto_ptr<Table> table(db->query("select * from t"));
Run Code Online (Sandbox Code Playgroud)
这个构造函数的定义是什么阻止它像我期望的那样工作?我认为初始化声明使用了构造函数.
这是我auto_ptr的构造函数(来自SGI STL):
explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
Run Code Online (Sandbox Code Playgroud)
小智 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
}
Run Code Online (Sandbox Code Playgroud)
"explicit"关键字阻止构造函数用于隐式类型转换.考虑以下两个函数原型:
void baz(foo<int> const &);
void quux(bar<int> const &);
Run Code Online (Sandbox Code Playgroud)
使用这些定义,尝试使用int指针调用这两个函数:
baz(&a); // fails
quux(&a); // succeeds
Run Code Online (Sandbox Code Playgroud)
在quux的情况下,int指针被隐式转换为bar.
编辑:要扩展其他人评论的内容,请考虑以下(相当愚蠢)代码:
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.
}
Run Code Online (Sandbox Code Playgroud)
你需要使用
auto_ptr<Table> table = auto_ptr<Table>(db->query("select * from t"));
Run Code Online (Sandbox Code Playgroud)
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"));
Run Code Online (Sandbox Code Playgroud)
构造函数声明为显式,这意味着它不会用于隐式类型转换.由于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
Run Code Online (Sandbox Code Playgroud)