如何通过编译错误找到C++复制构造函数的使用位置

how can I find where a C++ copy constructor is being USED via a compile error?

本文关键字:构造函数 位置 复制 C++ 编译 何通过 错误      更新时间:2023-10-16

简而言之:有没有什么方法可以修改类定义,使其无论在哪里使用,都无法在复制构造函数的使用点编译?

我有一个很大的项目,正在清理一些类定义。有一个类我明确不想在上面使用复制构造函数(为了讨论起见,让我们忽略为什么会这样),为了安全起见,我想我只会将复制构造函数定义为私有的,而不是实际实现它…这样,如果我试图在任何地方使用它,它都会引发编译错误。瞧,它编译得很好,但我有一个链接器错误。。。找不到复制构造函数实现!大概这意味着它在某个地方使用,但我找不到它在哪里使用。顺便说一下,这是Visual Studio 2010。所以我的问题是,有没有什么方法可以修改类定义,使其在使用时无法编译?

class Sample {
private:
    // not implemented
    Sample( const Sample& rhs );
    Sample& operator=( const Sample& rhs );
public:
    // implemented
    Sample();
...
};
Sample *samp1 = new Sample;
Sample *samp2 = new Sample( *samp1 ); // <<-- inaccessible here!  this works

大概是因为我没有遇到编译错误,而是遇到了链接器错误,这意味着类本身(或朋友)正在进行复制构造的创建(因为这就是访问私有构造函数的全部权限),但我肯定找不到!

在C++11中,您可以将定义更改为

class Sample {
private:
    // not implemented
    Sample( const Sample& rhs ) = delete;
    Sample& operator=( const Sample& rhs ) = delete;
public:
    // implemented
    Sample();
...
};

在C++11之前,这通常是通过从声明私有复制构造函数(如boost::NonCopyAble)的类继承来完成的(您可以简单地复制这个类,它只有几行)。在这种情况下,您的类(或任何朋友或子类)也无法访问复制构造函数,它将生成编译时错误。

从不可压缩类继承:

class noncopyable
{
private:
    // not implemented
    noncopyable( const noncopyable& rhs );
    noncopyable& operator=( const noncopyable& rhs );
};

class Sample : private noncopyable {
private:
    // not implemented
    Sample( const Sample& rhs );
    Sample& operator=( const Sample& rhs );
public:
    // implemented
    Sample();
    // ...
};
Sample *samp1 = new Sample;
Sample *samp2 = new Sample( *samp1 ); // <<-- compile-time error

即使您没有C++11,这也可以很好地工作(其他地方提到的delete方法可能更可取)。

链接器生成的错误是什么?如果是LNK2019,应该很容易找到使用复制构造函数的函数:

MSDN称其格式为:

函数"function"中引用的未解析外部符号"symbol"

如果查看此错误消息,您可以找到调用未定义的复制构造函数的方法。

您是否试图在编译过程中获取模块+行号?尝试将复制构造函数模板化:

class A
{
  public:
  template< typename T >
  A( A const & )
  {
  }
  A()
  {
  }
};
int main( void )
{
 A a;
 A b( a ); // main.cpp(43) : error C2558: class 'A' : no copy constructor available or copy constructor is declared 'explicit'
 return ( 0 );
}

如果成员是私有的,那么如果它没有访问私有成员的权限,那么您应该已经在使用位置收到错误。

要在do具有私有访问权限的函数中得到相同的错误,您必须将私有副本ctor声明放在它们没有访问权限的地方,比如作为基类的私有成员。

VS2010还不支持它,但将函数声明为已删除也可以。

我记得,如果您声明它为inline,有时您会收到一个编译器错误,说它是内联声明的,但从未定义过。那是一段时间前的事了,还有gcc。YMMV。

[显示不起作用;留给子孙后代。]