0

私は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(); それはなぜですか?

前もって感謝します

4

3 に答える 3

1

コピーコンストラクターはありますが、変換コンストラクターは明示的であり、これがエラーの原因です。

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

つまり、aを暗黙的にに変換することCar*はできません。auto_ptr<Car>

CarPtr au_ptr2 = new Car();

しようとします。これは、以下とは対照的に、コピー初期化と呼ばれます。

CarPtr au_ptr1 (new Car());

これは値の初期化です。CarPtr最初のバージョンは、から一時的なものを作成し、Car*それを使用してを初期化しようとしますau_ptr2。2つ目は、コピーコンストラクターを直接呼び出します。

のようなステートメント

int *i_ptr2(new int());

単に値-括弧内の値でポインタを初期化します。

于 2012-10-04T08:51:41.037 に答える
0

通常、オブジェクトにはコピー コンストラクターがあり、ポインターはオブジェクトではないため、コピー コンストラクター (または代入演算子またはデストラクター) はありません。より正確には、ポインターはデフォルトのコピーメカニズムに依存しています。

auto_ptrまたはその他のスマート ポインターについて話すとき、それらは単なるポインターの名前です。しかし実際には、それらはRAII メカニズムを使用するテンプレート化されたオブジェクトです。

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

CarPtr::CarPtr(...)対応するコンストラクターが作成されているため、コンパイルエラーが発生し、スタイルの初期化explicitを受け入れません。=

于 2012-10-04T08:55:00.380 に答える
0

生のポインターにはコンストラクターがありませんが、ほとんどの目的でコンストラクターがあるかのように使用できます。組み込み型はすべて、コピー コンストラクターを持つユーザー定義クラスと同様に、その型に変換可能な任意の型の値から初期化できます。

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

同じことを意味します。

この理由は基本的にテンプレートにあると思います。つまり、型Tをユーザー定義型のように使用でき、 or と記述T t(0);できT(0)T()たまたまT組み込み型である場合、意味はまったく同じですT t = 0;または(T)0または(T)0(再び)。実際、 の意味はT(0)定義(T)0、コンストラクターが何を持っていても同じTですが、C++ コードで C スタイルのキャストを使用しないように言う人は、その事実を無視しようとします ;-)

auto_ptr実際にはコピー コンストラクターがありますが、ほとんどのコピー コンストラクターとは異なり、const 以外のパラメーターを取り、その引数を変更します。unique_ptrそのため、C++11 では、コピー コンストラクターはありませんが、ムーブ コンストラクターはある が優先されて廃止されました。

Luchian が言うように、問題CarPtr au_ptr2 = new Car();は (単なる) コピー コンストラクターではなく、 , , の型から への暗黙的な変換がないことでもnew Car();ありCar*ますauto_ptr<Car>。コピーの初期化では、RHS を LHS の型に暗黙的に変換してから、それを LHS にコピーしようとします。この例では、どちらも失敗します。直接の初期化は、明示的な変換を使用することが許可されており、コピーを必要としないため、成功します。

組み込み型がコンストラクターを持っているかのように動作しない 1 つの方法は、既定の初期化です。あなたは書ける:

int i = int();

ゼロにi初期化されることが保証されています。したがって、ゼロに設定する引数なしのコンストラクターがあると想像するかもしれません。しかし、int本当にそのコンストラクターを持つクラス型である場合は、次のように記述します。

int i;

また、ゼロであることを保証iしますが、そうではありません(少なくとも、関数スコープではありません)。

ところで、これらすべてに興奮しすぎて、いわゆる「最も厄介な解析」を誤って呼び出してはいけません。

int i();

int i(void);ではなくと同等int i(0);です。整数変数ではなく、関数を宣言します。

于 2012-10-04T09:14:25.613 に答える