我遇到了复制构造函数错误,但不知道我对这个错误的想法是否正确
I've met an copy constructor error, but don't know if my thought about this error is correct
我正在编写一个名为 StackGuard 的 unique_ptr-like class,并尝试创建两个复制构造函数:
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() {
我想到了这个错误,但不知道对不对。
我的想法是:
传值拷贝构造函数需要使用拷贝构造函数来拷贝参数,在这种情况下,它会递归调用自己,导致无限调用。
我也想知道,为什么编译器会给出 "does not match any in class" 错误,因为它有一个匹配项。
您关于复制构造函数必须递归调用自身的假设是正确的。因此,标准不允许按值声明复制构造函数。这意味着只有第二个版本是合法的。
另一个构造函数是合法的。但是,您通常应该通过 const 引用来声明复制构造函数。构造函数不应修改其输入,因此您应该让编译器为您强制执行保证。使用 const 引用还可以让您复制 const 对象,否则您无法做到这一点。
来自[class.copy]:
A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified)
X and either there are no other parameters or else all other parameters have default arguments. A member
function template is never instantiated to produce such a constructor signature.
您的构造函数 StackGuard(StackGuard<T> )
格式错误。这里的问题与递归无关:这样的构造函数会导致歧义。考虑等价物:
void foo(int ) { }
void foo(int& ) { }
int i;
foo(i); // error: ambiguous
如果允许这样的构造函数,这个冒名顶替的复制构造函数和真正的(隐式或显式)复制构造函数之间总会有歧义。
此外,"unique-ptr like" 不建议我复制。您需要编写一个移动构造函数。如果您无法访问 C++11,则需要查看 auto_ptr
的实现方式并从那里复制。
我正在编写一个名为 StackGuard 的 unique_ptr-like class,并尝试创建两个复制构造函数:
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() {
我想到了这个错误,但不知道对不对。
我的想法是:
传值拷贝构造函数需要使用拷贝构造函数来拷贝参数,在这种情况下,它会递归调用自己,导致无限调用。
我也想知道,为什么编译器会给出 "does not match any in class" 错误,因为它有一个匹配项。
您关于复制构造函数必须递归调用自身的假设是正确的。因此,标准不允许按值声明复制构造函数。这意味着只有第二个版本是合法的。
另一个构造函数是合法的。但是,您通常应该通过 const 引用来声明复制构造函数。构造函数不应修改其输入,因此您应该让编译器为您强制执行保证。使用 const 引用还可以让您复制 const 对象,否则您无法做到这一点。
来自[class.copy]:
A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified) X and either there are no other parameters or else all other parameters have default arguments. A member function template is never instantiated to produce such a constructor signature.
您的构造函数 StackGuard(StackGuard<T> )
格式错误。这里的问题与递归无关:这样的构造函数会导致歧义。考虑等价物:
void foo(int ) { }
void foo(int& ) { }
int i;
foo(i); // error: ambiguous
如果允许这样的构造函数,这个冒名顶替的复制构造函数和真正的(隐式或显式)复制构造函数之间总会有歧义。
此外,"unique-ptr like" 不建议我复制。您需要编写一个移动构造函数。如果您无法访问 C++11,则需要查看 auto_ptr
的实现方式并从那里复制。