[英]Do pointers have copy constructors?
我正在從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();
這是為什么?
提前致謝
它確實有一個復制構造函數, 但是轉換構造函數是顯式的 ,這是導致錯誤的原因:
explicit auto_ptr (X* p=0) throw();
這意味着Car*
不能隱式轉換為auto_ptr<Car>
,這就是
CarPtr au_ptr2 = new Car();
嘗試做。 這稱為復制初始化 ,與:
CarPtr au_ptr1 (new Car());
這是值初始化 。 第一個版本將嘗試從Car*
創建一個臨時CarPtr
並將其用於初始化au_ptr2
。 第二個直接調用復制構造函數。
像這樣的陳述
int *i_ptr2(new int());
只需使用括號中的值對指針進行值初始化。
通常,對象具有復制構造函數,而指針不是對象,因此它們沒有復制構造函數(或賦值運算符或析構函數)。 更准確地說,指針依賴於默認的復制機制。
當您談論auto_ptr
或任何其他智能指針時,它們只是指針的名稱。 但是實際上,它們是使用RAII機制的模板對象 。
CarPtr au_ptr2 = new Car(); // this is initialization not assignment
給出編譯錯誤,因為相應的CarPtr::CarPtr(...)
構造函數被explicit
構造,因此它不接受=
樣式初始化。
原始指針沒有構造函數,但是對於大多數目的,它們可以像使用它們一樣使用。 內置類型都可以從可轉換為其類型的任何類型的值初始化,就像帶有復制構造函數的用戶定義類一樣。
int *i_ptr1=new int();
int *i_ptr2(new int());
意思是一樣的。
我認為這樣做的原因基本上是模板:這意味着您可以像使用用戶定義的類型一樣使用類型T
,並寫入T t(0);
或T(0)
或T()
,並且當T
恰好是內置類型時,其含義與T t = 0;
完全相同T t = 0;
或(T)0
或(T)0
(再次)。 實際上,無論定義 T
具有什么構造函數, T(0)
的含義都與(T)0
相同,但是告訴您不要在C ++代碼中使用C樣式強制轉換的人會嘗試忽略這一事實;-)
實際上, auto_ptr
確實具有一個復制構造函數,但是與大多數復制ctor不同,它使用一個非const參數,並修改其參數。 這就是為什么在C ++ 11中不贊成使用unique_ptr
,后者沒有副本構造函數,但確實具有move構造函數。
如Luchian所說, CarPtr au_ptr2 = new Car();
的問題CarPtr au_ptr2 = new Car();
不只是復制構造函數,還缺少new Car();
類型的隱式轉換new Car();
Car*
到auto_ptr<Car>
。 復制初始化嘗試將RHS隱式轉換為LHS的類型,然后將其復制到LHS。 兩者均在此示例中失敗。 直接初始化允許使用顯式轉換,並且不需要副本,因此可以成功。
內置類型不表現為具有構造函數的一種方式是默認初始化。 你可以寫:
int i = int();
並且i
保證初始化為零。 因此,您可能會想到它具有一個無參數的構造函數,將其設置為零。 但是如果int
實際上是具有該構造函數的類類型,則編寫:
int i;
還可以保證i
為零,但不會(至少不在函數范圍內)。
順便說一句,不要對所有這些都太興奮,而會意外地調用所謂的“最令人煩惱的解析”。
int i();
等價於int i(void);
,而不是int i(0);
。 它聲明一個函數,而不是整數變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.