为什么 auto_ptr 构造不能使用 = 语法

发布于 2024-07-17 17:16:15 字数 566 浏览 5 评论 0原文

我遇到了一个对我来说没有多大意义的编译器错误:

#include <memory>
using namespace std;

auto_ptr<Table> table = db->query("select * from t");

error: conversion from 'Table*' to non-scalar type 'std::auto_ptr< 表>' 但是

,以下行确实有效:

auto_ptr<Table> table(db->query("select * from t"));

构造函数的这个定义是什么导致它无法按我的预期工作? 我认为初始化声明使用了构造函数。

这是我的 auto_ptr 的构造函数(来自 SGI STL):

explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

I ran into a compiler error that didn't make much sense to me:

#include <memory>
using namespace std;

auto_ptr<Table> table = db->query("select * from t");

error: conversion from 'Table*' to non-scalar type 'std::auto_ptr< Table>' requested

However, the following line does work:

auto_ptr<Table> table(db->query("select * from t"));

What is it about this definiton of the constructor that prevents it from working as I expect? I thought that initialized declarations used the constructors.

Here's my auto_ptr's constructor (from the SGI STL):

explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

飘然心甜 2024-07-24 17:16:15

这是“显式”关键字。

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 指针被隐式转换为 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.
}

It's the "explicit" keyword.

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
}

The "explicit" keyword prevents the constructor from being used for implicit type conversions. Consider the following two function prototypes:

void baz(foo<int> const &);
void quux(bar<int> const &);

With those definitions, try calling both functions with an int pointer:

baz(&a);  // fails
quux(&a); // succeeds

In the case of quux, your int pointer was implicitly converted to a bar.

EDIT: To expand on what other people commented, consider the following (rather silly) code:

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.
}
喜你已久 2024-07-24 17:16:15

您需要使用

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"));

You need to use

auto_ptr<Table> table = auto_ptr<Table>(db->query("select * from t"));

auto_ptr does not define an assignment operator for it's template type. The only allowed assignment is from another auto_ptr (and it's constructor from the pointer is explicit). This is done to protect accidental misuse of auto_ptr, as auto_ptr assumes ownership of the memory.

My guess is that you need the assignment form to use multiple queries after another like:

// 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"));
来世叙缘 2024-07-24 17:16:15

构造函数被声明为显式,这意味着它不会用于隐式类型转换。 隐式转换为 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

The constructor is declared as explicit, which means that it won't be used for implicit type casting. Implicit conversion to auto_ptr could easily lead to undesirable situations since the auto_ptr is taking ownership of the pointer.

For example, if auto_ptr would allow implicit conversion from a pointer and you accidentally passed a pointer to a method taking an auto_ptr the pointer would be silently converted to an auto_ptr and subsequently deleted when the function ends, even if that wasn't the intention. But by marking the constructor as explicit conversion can no longer happen silently and by calling the constructor you clearly express the intention of passing ownership to the auto_ptr, thus avoiding any potential confusion.

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
暮光沉寂 2024-07-24 17:16:15

添加到lothar所说的内容:由于auto_ptr构造函数是使用explicit关键字声明的,因此您需要使用显式强制转换来创建auto_ptr一个原始指针。 (在引入显式之前,隐式转换是许多新的(以及经验丰富的)C++ 开发人员的祸根。)

Adding to what lothar said: Because the auto_ptr constructor is declared with the explicit keyword, you need to use an explict cast to create an auto_ptr from a raw pointer. (Before the introduction of explicit, implicit casting was the bane of many a new -- and experienced) C++ developer.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文