4

C++ で奇妙な問題に直面しています。説明をいただければ幸いです。このスニペットはコンパイルに失敗します:

size_t bufLength = 18;
char* buffer = new char[bufLength];
auto_array_ptr<char> pBuffer1 = buffer;  // fails
auto_array_ptr<char> pBuffer2(buffer);

上記の 3 行目は で失敗しNo viable constructor copying variable of type 'auto_array_ptr<char>'ます。次の行は問題なくコンパイルされることに注意してください。

Q1) これ自体が私には奇妙です。割り当てによる初期化は、必要に応じて初期化子による初期化に変換されると思いました。2 番目が成功するのに、なぜ 1 番目が失敗する可能性があるのでしょうか?

Q2) しかし、私にとっての本当のパズルは、クラスからコンストラクターを削除すると、失敗した行が成功することです:コンストラクター。ここで何が起こっているのか理解するのに本当に苦労しています。auto_array_ptrauto_array_ptr(auto_array_ptr)

コンパイラがここで何をしようとしているのか、ここでシナリオを想像することができます:

1- void を探しますoperator=(char *p)。見つかりません。引数 ( ) を昇格できるかどうか見てみましょうbuffer。2-ああああ、ありoperator=(auto_array_ptr&)ます。に昇格できれば勝ちbufferですauto_array_ptr。それを行うコンストラクタを探してみましょう。3-ああ、auto_array_ptr(auto_array_ptr&)コンストラクターがあります。bufferそれでは、そのコンストラクター ( ) を使用して一時変数を作成しましょうtemp。4-今operator=(auto_array_ptr&)、メソッドを使用してみてください。しかし残念なことに、その引数は ではなくconst、実際には使用できません。エラーを報告します。

しかし、このシナリオは説得力がありません。const1 つは、コンパイラがステップ 2の問題に気付く可能性があるauto_array_ptr(char *)こと bufferです。次に、クラスに a を追加しoperator=(char *p)ても、エラーは消えません。最後に、ヘルプを削除する理由が説明されていませんauto_array_ptr(auto_array_ptr&)

もちろん、ソースが必要ですauto_array_ptr。ここにあります:

template<class T>
class auto_array_ptr
{
public:
    auto_array_ptr(T *p = 0) : ptr(p) {}
    auto_array_ptr(auto_array_ptr<T>& a) : ptr(a.release()) {}  // remove this line to compile
    ~auto_array_ptr() {if(ptr != 0) {delete[] ptr; ptr = 0;}}

    void operator=(auto_array_ptr<T>& a) {if(&a != this) reset(a.release());}
//    void operator=(T *p) { if(p != ptr) reset(p);}    // adding this doesn't help

    T& operator[](int i) const {return ptr[i];}
    T& operator[](unsigned int i) const {return ptr[i];}
    operator T*() const {return ptr;}
    T* get() const {return ptr;}

    T* release() {T* tmp = ptr; ptr = 0; return tmp;}

    void reset(T *p = 0) {if(ptr != 0) {delete[] ptr;}; ptr = p;}

private:
    T *ptr;
};

コンパイラは、Mac OS X Lion の Xcode 4.4 で実行される最新バージョンの Clang です。LLVM 3.1に基づいていると思います。Xcode 4.5 の少し新しいバージョンは、まったく同じように動作します。

ありがとう。

4

2 に答える 2

4
auto_array_ptr<char> pBuffer1 = buffer;  // fails

から作成temporary auto_array_ptr<char>bufferてにコピーしpBuffer1ます。

auto_array_ptr(auto_array_ptr<T>& a)

あなたのcopy c-tor受け取りreference。にバインドできないtemporaryためreference、コンパイルは失敗します。

Q2)しかし、私にとっての本当のパズルは、auto_array_ptrクラスからコンストラクター(auto_array_ptr(auto_array_ptr)コンストラクター)を削除すると、失敗した行が成功することです。ここで何が起こっているのか理解するのに本当に苦労しています。

コンパイラはで作成copy c-torしますsignature

auto_array_ptr(const auto_array_ptr&)
于 2012-09-03T12:55:13.427 に答える
3

これはコピーの初期化です:

auto_array_ptr<char> pBuffer1 = buffer;  // fails

これにより、一時的なauto_array_ptr<char>fromが作成され、のコピーコンストラクターbufferが使用されます。(最適化の対象)コピーコンストラクターが次のように宣言されているため、これは失敗します。pBuffer1

auto_array_ptr(auto_array_ptr<T>& a)

const一時的なものは非参照にバインドできません。に変更します

auto_array_ptr(const auto_array_ptr<T>& a)

これは直接初期化です。

auto_array_ptr<char> pBuffer2(buffer);

変換コンストラクターのみを使用します。

于 2012-09-03T12:56:33.863 に答える