简体   繁体   English

指针是否具有复制构造函数?

[英]Do pointers have copy constructors?

I am transiting from C pointers to C++ ones,now learning about auto_ptr. 我正在从C指针过渡到C ++指针,现在正在学习有关auto_ptr的知识。 Here is the program I tried: 这是我尝试过的程序:

#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());
}

Statements like the following mean what? 如下语句表示什么?

int *i_ptr2(new int());
Car *norm_ptr2(new Car()); 

The statement mentioned above compiled successfully.And the following one,throws a compilation error - CarPtr au_ptr2 = new Car(); 上述语句已成功编译。接下来的语句引发了编译错误CarPtr au_ptr2 = new Car(); Why is that? 这是为什么?

Thanks in Advance 提前致谢

It does have a copy constructor, but the conversion constructor is explicit , which is what is causing the error: 它确实有一个复制构造函数, 但是转换构造函数是显式的 ,这是导致错误的原因:

explicit auto_ptr (X* p=0) throw();

Which means a Car* can't be implicitly converted to a auto_ptr<Car> , which is what 这意味着Car*不能隐式转换为auto_ptr<Car> ,这就是

CarPtr au_ptr2 = new Car();

attempts to do. 尝试做。 This is called copy-initialization , as opposed to: 这称为复制初始化 ,与:

CarPtr au_ptr1 (new Car());

which is value-initialization . 这是值初始化 The first version will attempt to create a temporary CarPtr from a Car* and use it to initialize au_ptr2 . 第一个版本将尝试从Car*创建一个临时CarPtr并将其用于初始化au_ptr2 The second one calls the copy constructor directly. 第二个直接调用复制构造函数。

Statements like 像这样的陈述

int *i_ptr2(new int());

simply value-initialize the pointer with the value in the parenthesis. 只需使用括号中的值对指针进行值初始化。

Typically objects have copy constructor and pointers are not objects so they don't have copy constructor (or assignment operator or destructor). 通常,对象具有复制构造函数,而指针不是对象,因此它们没有复制构造函数(或赋值运算符或析构函数)。 More precisely, pointers rely on the default copying mechanism. 更准确地说,指针依赖于默认的复制机制。

When you talk about auto_ptr or any other smart pointers, they are just pointer namesakes. 当您谈论auto_ptr或任何其他智能指针时,它们只是指针的名称。 But in actual they are templatized objects which use the RAII mechanism. 但是实际上,它们是使用RAII机制的模板对象

CarPtr au_ptr2 = new Car();  // this is initialization not assignment

gives compilation error because corresponding CarPtr::CarPtr(...) constructor is made explicit , so it doesn't accept the = style initialization. 给出编译错误,因为相应的CarPtr::CarPtr(...)构造函数被explicit构造,因此它不接受=样式初始化。

Raw pointers don't have constructors, but for most purposes they can be used as if they do. 原始指针没有构造函数,但是对于大多数目的,它们可以像使用它们一样使用。 The built-in types can all be initialized from a value of any type convertible to their type, just like a user-defined class with a copy constructor can. 内置类型都可以从可转换为其类型的任何类型的值初始化,就像带有复制构造函数的用户定义类一样。

int *i_ptr1=new int();
int *i_ptr2(new int());

mean the same thing. 意思是一样的。

I think the reason for this is basically templates: it means that you can use a type T as though it were a user-defined type, and write T t(0); 我认为这样做的原因基本上是模板:这意味着您可以像使用用户定义的类型一样使用类型T ,并写入T t(0); or T(0) or T() , and when T happens to be a built-in type the meaning is exactly the same as T t = 0; T(0)T() ,并且当T恰好是内置类型时,其含义与T t = 0;完全相同T t = 0; or (T)0 or (T)0 (again). (T)0(T)0 (再次)。 Actually, the meaning of T(0) is by definition the same as (T)0 regardless of what constructors T has, but people who tell you not to use C-style casts in C++ code try to ignore that fact ;-) 实际上,无论定义 T具有什么构造函数, T(0)的含义都与(T)0相同,但是告诉您不要在C ++代码中使用C样式强制转换的人会尝试忽略这一事实;-)

auto_ptr does in fact have a copy constructor, but unlike most copy ctors it takes a non-const parameter, and modifies its argument. 实际上, auto_ptr确实具有一个复制构造函数,但是与大多数复制ctor不同,它使用一个非const参数,并修改其参数。 That's why in C++11 it's deprecated in favor of unique_ptr , which doesn't have a copy constructor but does have a move constructor. 这就是为什么在C ++ 11中不赞成使用unique_ptr ,后者没有副本构造函数,但确实具有move构造函数。

As Luchian says, the problem with CarPtr au_ptr2 = new Car(); 如Luchian所说, CarPtr au_ptr2 = new Car();的问题CarPtr au_ptr2 = new Car(); isn't (just) the copy constructor, it's also the lack of an implicit conversion from the type of new Car(); 不只是复制构造函数,还缺少new Car();类型的隐式转换new Car(); , Car* , to auto_ptr<Car> . Car*auto_ptr<Car> Copy initialization tries to implicitly convert the RHS to the type of the LHS, and then copy it to the LHS. 复制初始化尝试将RHS隐式转换为LHS的类型,然后将其复制到LHS。 Both of those fail in this example. 两者均在此示例中失败。 Direct initialization is allowed to use explicit conversions and doesn't need a copy, so it succeeds. 直接初始化允许使用显式转换,并且不需要副本,因此可以成功。

One way in which built-in types don't behave as if they have constructors is default initialization. 内置类型不表现为具有构造函数的一种方式是默认初始化。 You can write: 你可以写:

int i = int();

and i is guaranteed initialized to zero. 并且i保证初始化为零。 So you might imagine that it has a no-args constructor that sets it to zero. 因此,您可能会想到它具有一个无参数的构造函数,将其设置为零。 But if int were really a class type with that constructor, then writing: 但是如果int实际上是具有该构造函数的类类型,则编写:

int i;

would also guarantee i is zero, and it doesn't (at least, not in function scope). 还可以保证i为零,但不会(至少不在函数范围内)。

By the way, don't get too excited by all this and accidentally invoke the so-called "most vexing parse". 顺便说一句,不要对所有这些都太兴奋,而会意外地调用所谓的“最令人烦恼的解析”。

int i();

is equivalent to int i(void); 等价于int i(void); , not int i(0); ,而不是int i(0); . It declares a function, not an integer variable. 它声明一个函数,而不是整数变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM