我正在从C指针转换到C ++指针,现在正在学习auto_ptr。这是我尝试的程序:
#include <iostream>
#include <memory>
#include "Car.h"
using namespace std;
typedef auto_ptr<Car> CarPtr;
int main() {
CarPtr au_ptr1(new Car());
CarPtr au_ptr2 = new Car();
Car *norm_ptr1 = new Car();
Car *norm_ptr2(new Car());
int *i_ptr1=new int();
int *i_ptr2(new int());
}
以下语句意味着什么?
int *i_ptr2(new int());
Car *norm_ptr2(new Car());
上面提到的语句编译成功。以下一个,抛出编译错误 - CarPtr au_ptr2 = new Car();
那是为什么?
先谢谢
答案 0 :(得分:1)
它有一个复制构造函数,但是转换构造函数是显式的,这是导致错误的原因:
explicit auto_ptr (X* p=0) throw();
这意味着Car*
无法隐式转换为auto_ptr<Car>
,这就是
CarPtr au_ptr2 = new Car();
尝试做。这称为复制初始化,而不是:
CarPtr au_ptr1 (new Car());
值初始化。第一个版本将尝试从CarPtr
创建临时Car*
并使用它来初始化au_ptr2
。第二个直接调用复制构造函数。
之类的陈述
int *i_ptr2(new int());
只需用括号中的值初始化指针。
答案 1 :(得分:0)
通常,对象具有复制构造函数,而指针不是对象,因此它们没有复制构造函数(或赋值运算符或析构函数)。更准确地说,指针依赖于默认的复制机制。
当你谈到auto_ptr
或任何其他智能指针时,它们只是指针同名。但实际上它们是使用RAII机制的模板化对象。
CarPtr au_ptr2 = new Car(); // this is initialization not assignment
给出了编译错误,因为相应的CarPtr::CarPtr(...)
构造函数是explicit
,所以它不接受=
样式初始化。
答案 2 :(得分:0)
原始指针没有构造函数,但是对于大多数用途,它们可以像使用它们一样使用。内置类型都可以从任何可转换为其类型的类型的值初始化,就像具有复制构造函数的用户定义类一样。
int *i_ptr1=new int();
int *i_ptr2(new int());
意思是同样的事情。
我认为其原因基本上是模板:这意味着您可以使用类型T
,就像它是用户定义的类型一样,并写入T t(0);
或T(0)
或T()
,当T
恰好是内置类型时,其含义与T t = 0;
或(T)0
或(T)0
(再次)完全相同。实际上,T(0)
的含义定义与(T)0
相同,无论构造函数T
有什么,但是那些告诉你不要使用C风格的人C ++代码中的强制转换试图忽略这一事实; - )
auto_ptr
实际上有一个复制构造函数,但与大多数复制ctors不同,它采用非const参数,并修改其参数。这就是为什么在C ++ 11中它被弃用而不是unique_ptr
,它没有复制构造函数但是有一个移动构造函数。
正如Luchian所说,CarPtr au_ptr2 = new Car();
的问题不仅仅是(仅)复制构造函数,而是缺少从new Car();
,Car*
类型的隐式转换, auto_ptr<Car>
。复制初始化尝试隐式将RHS转换为LHS的类型,然后将其复制到LHS。在这个例子中,这两个都失败了。允许直接初始化使用显式转换,不需要副本,因此成功。
内置类型不具有构造函数的一种方式是默认初始化。你可以写:
int i = int();
和i
保证初始化为零。所以你可能会想象它有一个no-args构造函数将它设置为零。但是如果int
实际上是具有该构造函数的类类型,那么写:
int i;
也会保证i
为零,而不是(至少不在函数范围内)。
顺便说一下,不要因为这一切而太兴奋,不小心引用了所谓的“最令人烦恼的解析”。
int i();
相当于int i(void);
,而不是int i(0);
。它声明了一个函数,而不是整数变量。