【问题标题】:I've met an copy constructor error, but don't know if my thought about this error is correct我遇到了一个复制构造函数错误,但不知道我对这个错误的想法是否正确
【发布时间】:2016-02-05 13:30:10
【问题描述】:

我正在编写一个类似于 unique_ptr 的类,称为 StackGuard,并尝试创建两个复制构造函数:

template<typename T>    
class StackGuard{
  T* thePtr;   //To store the raw pointer.
               //something here...
  StackGuard(StackGuard<T>& newPtr) throw();
  StackGuard(StackGuard<T> newPtr) throw();  //I know this is not the right way
              //something here...
};

template<typename T>
StackGuard<T>::StackGuard(StackGuard<T>& newPtr) throw(){
    thePtr = newPtr.thePtr;
    newPtr.thePtr = NULL;
}

template<typename T>
StackGuard<T>::StackGuard(StackGuard<T> newPtr) throw(){
    thePtr = newPtr.thePtr;
    newPtr.thePtr = NULL;
}

但它不起作用。编译器说

error: invalid constructor; you probably meant ‘StackGuard<T> (const StackGuard<T>&)’
     StackGuard(StackGuard<T> newPtr) throw();
                                            ^
error: prototype for ‘StackGuard<T>::StackGuard(StackGuard<T>)’ 
does not match any in class ‘StackGuard<T>’
  StackGuard<T>::StackGuard(StackGuard<T> newPtr) throw(){
  ^
error: candidates are: StackGuard<T>::StackGuard(const StackGuard<T>&)
  StackGuard<T>::StackGuard(const StackGuard<T>& newPtr) throw(){
  ^
error:                 StackGuard<T>::StackGuard(T*)
  StackGuard<T>::StackGuard(T* guarded = NULL) throw() {

我有想过这个错误,但不知道对不对。

我的想法是:

传值拷贝构造函数需要使用拷贝构造函数来拷贝参数,在这种情况下,它会递归调用自身,导致无限调用。

我也想知道,为什么编译器会给出“与类中的任何内容不匹配”错误,因为它有匹配项。

【问题讨论】:

  • “copy-constructor”和“unique_ptr like”不兼容……后者只能移动。
  • StackGuard(StackGuard&lt;T&gt; newPtr) 不是复制构造函数;复制构造函数只能通过左值引用接受它们的参数。 .我什至不认为这是一个合法的功能

标签: c++ copy-constructor pass-by-value


【解决方案1】:

来自[class.copy]:

如果类 X 的第一个参数是类型(可选 cv-qualified),则其构造函数的声明是格式错误的 X 并且要么没有其他参数,要么所有其他参数都有默认参数。成员 函数模板永远不会被实例化以产生这样的构造函数签名。

您的构造函数StackGuard(StackGuard&lt;T&gt; ) 格式不正确。这里的问题与递归无关:这样的构造函数会导致歧义。考虑等价物:

void foo(int ) { }
void foo(int& ) { }

int i;
foo(i); // error: ambiguous

如果允许这样的构造函数,那么这个冒名顶替的复制构造函数和真正的(隐式或显式)复制构造函数之间总是存在歧义的。

此外,“unique-ptr like”不建议我复制。您需要编写一个移动构造函数。如果您无法访问 C++11,则需要查看 auto_ptr 的实现方式并从那里复制。

【讨论】:

  • 感谢您的回答,这种歧义是编译器大喊大叫的原因吗?关于可复制的东西,如果我想交出 StackGuard 对象持有的对象的所有权怎么办?
  • @Curtis2 你移动它。 StackGuard&lt;T&gt; new_obj = std::move(old_obj);
  • 啊哈,就是这样!非常感谢,很有帮助! @巴里
【解决方案2】:

您认为复制构造函数必须递归调用自身的假设是正确的。出于这个原因,标准不允许按值声明的复制构造函数。这意味着只有第二个版本是合法的。

另一个构造函数是合法的。但是,您通常应该通过 const 引用来声明复制构造函数。构造函数不应该修改他们的输入,所以你应该让编译器为你强制执行保证。使用 const 引用还可以让您复制 const 对象,否则您无法这样做。

【讨论】:

  • 我认为,既然我们需要避免双重删除,复制构造函数需要修改它的输入,并将thePtr指向NULL
  • 多哈。你是对的,我没有考虑用例。 通常你应该使用 const 引用。我已经编辑了答案。
猜你喜欢
  • 2015-02-05
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 2020-10-11
  • 2021-05-11
  • 2021-05-18
  • 1970-01-01
  • 2018-04-12
相关资源
最近更新 更多