C ++构造函数阻止成功编译

时间:2012-09-03 12:52:10

标签: c++ copy-constructor initializer-list

我在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中稍微更新的版本表现完全相同。

感谢。

2 个答案:

答案 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);

仅使用转换构造函数。