为什么auto_ptr构造不能使用= syntax

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.只需使用显式构造函数:auto_ptr <Table> table(db-> query("select*from t")); 或者移动shared_ptr. (2认同)

lot*_*har 8

你需要使用

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)


Sam*_*ter 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
Run Code Online (Sandbox Code Playgroud)