我在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)这本身对我来说很奇怪。我认为在必要时使用初始化将赋值初始化转换为初始化。如果第二次成功,为什么第一次失败?
Q2)但对我来说真正的难题是,当我从auto_array_ptr
类<{1}}类中移除构造函数时,失败的行成功了:auto_array_ptr(auto_array_ptr)
构造函数。我真的很难理解这里发生了什么。
我可以想象一下编译器可能在这里尝试做什么的场景:
1-寻找无效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
问题是第2步。此外,它可以直接使用auto_array_ptr(char *)
而不是尝试提升buffer
。然后,如果我向类中添加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中稍微更新的版本表现完全相同。
感谢。
答案 0 :(得分: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&)
答案 1 :(得分:3)
这是复制初始化:
auto_array_ptr<char> pBuffer1 = buffer; // fails
这会从auto_array_ptr<char>
创建一个临时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);
仅使用转换构造函数。