指针有复制构造函数吗?

时间:2012-10-04 08:50:27

标签: c++ pointers smart-pointers

我正在从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(); 那是为什么?

先谢谢

3 个答案:

答案 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);。它声明了一个函数,而不是整数变量。