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)这本身对我来说很奇怪。我认为在必要时将使用赋值进行初始化转换为使用初始化程序进行初始化。如果第二个成功,为什么第一个会失败?

Q2)但对我来说真正的难题是当我从类中删除构造函数时失败的行成功了:构造函数。我真的很难理解这里发生了什么。auto_array_ptrauto_array_ptr(auto_array_ptr)

我可以在这里想象一个编译器可能在这里尝试做的场景:

1- 寻找一个 void operator=(char *p)。未找到。让我们看看我们是否可以提升论点 ( buffer)。2-啊啊,有一个operator=(auto_array_ptr&)。因此,如果我能晋升bufferauto_array_ptr. 让我们寻找一个构造函数来做到这一点。3-啊啊有一个auto_array_ptr(auto_array_ptr&)构造函数。buffer因此,让我们使用该构造函数 ( )构造一个临时变量temp。4-现在尝试使用operator=(auto_array_ptr&), 方法。但是很糟糕:它的论点不是const,我实际上不能使用它。报告错误。

但这种情况并不令人信服。一方面,编译器可能会注意到const问题出在第 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>到.bufferpBuffer1

auto_array_ptr(auto_array_ptr<T>& a)

copy c-tor收到reference。您无法绑定temporaryreference,因此编译失败。

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>的 frombuffer然后使用复制构造函数for 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 回答