为什么 auto_ptr 不允许使用赋值语法进行初始化
Why auto_ptr initialization using the assignment syntax is not allowed
我正在通读这本书
C++ standard library book
这是我无法理解的部分:
Note that class auto_ptr<> does not allow you to initialize an object with an ordinary pointer by
using the assignment syntax.
std::auto_ptr<ClassA> ptr1(new ClassA); //ok
std::auto_ptr<ClassA> ptr2 = new ClassA; //error
我不明白为什么不允许。他们试图通过不允许使用赋值语法初始化来避免什么样的陷阱
无法使用赋值语法从原始指针初始化 auto_ptr
的事实是构造函数的副作用,该构造函数将原始指针标记为显式。将构造函数标记为显式的通常原因是为了防止这样的事情发生:
void take_ownership(std::auto_ptr<ClassA> ptr) {
// the pointer is deleted when this function ends
}
void foo() {
ClassA obj;
take_ownership(&obj); // oops, delete will be called on a pointer to
// an object which was not allocated with new
}
调用 take_ownership
函数是一个错误,因为 std::auto_ptr
构造函数上的显式 classifier。相反,您必须特意构造一个 auto_ptr
并将其传递给函数。
void foo() {
std::auto_ptr<ClassA> ptr(new ClassA);
take_ownership(ptr); // okay
}
当然这并不是完全不受滥用影响的(您仍然可以将非新对象传递给 auto_ptr
的构造函数),至少更容易发现何时发生滥用。
顺便说一句,std::auto_ptr
已弃用。这是一个非常破烂的class(由于引入时语言的限制)。请改用 std::unique_ptr
。
- I don't understand why it is not allowed.
乍一看直接初始化和复制初始化不是一回事
std::auto_ptr<ClassA> ptr1(new ClassA); //ok
std::auto_ptr<ClassA> ptr2 = new ClassA; //error
Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
所以如果你想通过复制初始化用原始指针初始化std::auto_ptr
,将需要转换构造函数,但std::auto_ptr
没有。
std::auto_ptr
的constructor以一个原始指针为参数是explicit
,禁止隐式转换
- What kind of pitfalls they were trying to avoid by not allowing initialization with assignment syntax
如果允许隐式转换,请考虑以下代码:
void f1(ClassA* p) { ... }
void f2(std::auto_ptr<ClassA> p) { ... }
...
ClassA* p = new ClassA;
f2(p); // call the wrong function, ownership is transfered to auto_ptr implicitly
p->something(); // UB, p has been deleted
delete p; // UB
std::auto_ptr
的定义如下:
template< class T > class auto_ptr;
template<> class auto_ptr<void>;
因此 auto_ptr
是 class 类型。让我们看看它的构造函数:
explicit auto_ptr( X* p = 0 );
auto_ptr( auto_ptr& r );
template< class Y >
auto_ptr( auto_ptr<Y>& r );
template< class Y >
auto_ptr( auto_ptr_ref<Y> m );
考虑第一个构造函数。我们可以使用指向 X
类型对象的指针作为参数来调用此构造函数:
std::auto_ptr<X> ptr1(new X); //ok
同时,第一个构造函数是explicit
,因此我们不能使用指向X
类型对象的指针隐式转换为auto_ptr<X>
.换句话说,我们不能通过指向 X
类型对象的指针直接初始化它。
std::auto_ptr<X> ptr1 = new X; //error; cannot implicitly transform
我正在通读这本书 C++ standard library book
这是我无法理解的部分:
Note that class auto_ptr<> does not allow you to initialize an object with an ordinary pointer by using the assignment syntax.
std::auto_ptr<ClassA> ptr1(new ClassA); //ok
std::auto_ptr<ClassA> ptr2 = new ClassA; //error
我不明白为什么不允许。他们试图通过不允许使用赋值语法初始化来避免什么样的陷阱
无法使用赋值语法从原始指针初始化 auto_ptr
的事实是构造函数的副作用,该构造函数将原始指针标记为显式。将构造函数标记为显式的通常原因是为了防止这样的事情发生:
void take_ownership(std::auto_ptr<ClassA> ptr) {
// the pointer is deleted when this function ends
}
void foo() {
ClassA obj;
take_ownership(&obj); // oops, delete will be called on a pointer to
// an object which was not allocated with new
}
调用 take_ownership
函数是一个错误,因为 std::auto_ptr
构造函数上的显式 classifier。相反,您必须特意构造一个 auto_ptr
并将其传递给函数。
void foo() {
std::auto_ptr<ClassA> ptr(new ClassA);
take_ownership(ptr); // okay
}
当然这并不是完全不受滥用影响的(您仍然可以将非新对象传递给 auto_ptr
的构造函数),至少更容易发现何时发生滥用。
顺便说一句,std::auto_ptr
已弃用。这是一个非常破烂的class(由于引入时语言的限制)。请改用 std::unique_ptr
。
- I don't understand why it is not allowed.
乍一看直接初始化和复制初始化不是一回事
std::auto_ptr<ClassA> ptr1(new ClassA); //ok
std::auto_ptr<ClassA> ptr2 = new ClassA; //error
Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
所以如果你想通过复制初始化用原始指针初始化std::auto_ptr
,将需要转换构造函数,但std::auto_ptr
没有。
std::auto_ptr
的constructor以一个原始指针为参数是explicit
,禁止隐式转换
- What kind of pitfalls they were trying to avoid by not allowing initialization with assignment syntax
如果允许隐式转换,请考虑以下代码:
void f1(ClassA* p) { ... }
void f2(std::auto_ptr<ClassA> p) { ... }
...
ClassA* p = new ClassA;
f2(p); // call the wrong function, ownership is transfered to auto_ptr implicitly
p->something(); // UB, p has been deleted
delete p; // UB
std::auto_ptr
的定义如下:
template< class T > class auto_ptr;
template<> class auto_ptr<void>;
因此 auto_ptr
是 class 类型。让我们看看它的构造函数:
explicit auto_ptr( X* p = 0 );
auto_ptr( auto_ptr& r );
template< class Y >
auto_ptr( auto_ptr<Y>& r );
template< class Y >
auto_ptr( auto_ptr_ref<Y> m );
考虑第一个构造函数。我们可以使用指向 X
类型对象的指针作为参数来调用此构造函数:
std::auto_ptr<X> ptr1(new X); //ok
同时,第一个构造函数是explicit
,因此我们不能使用指向X
类型对象的指针隐式转换为auto_ptr<X>
.换句话说,我们不能通过指向 X
类型对象的指针直接初始化它。
std::auto_ptr<X> ptr1 = new X; //error; cannot implicitly transform