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_ptr
auto_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
、実際には使用できません。エラーを報告します。
しかし、このシナリオは説得力がありません。const
1 つは、コンパイラがステップ 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 の少し新しいバージョンは、まったく同じように動作します。
ありがとう。