如何通过编译错误找到C ++拷贝构造函数的用途?

时间:2022-09-10 09:38:39

In short: is there some way I can modify a class definition such that it fails to compile at the point of use of a copy constructor no matter where it's used?

简而言之:我是否可以通过某种方式修改类定义,以便无论在何处使用它都无法在使用复制构造函数时进行编译?

I have a very large project and was cleaning up some class definitions. There's a class that I explicitly don't want to use copy constructors on (let's ignore why that is for the sake of this discussion), and in the interest of safety, I figured I'd just define the copy constructor as private and not actually implement it... that way it would throw a compile error if I tried to use it anywhere. Lo and behold, it compiles fine, but I have a linker error... the copy constructor implementation is not found! Presumably that means it's in use somewhere, but I'm unable to find where it's being used. This is Visual Studio 2010 by the way. So my question is, is there some way I can modify the class definition such that it fails to compile at the point of use?

我有一个非常大的项目,正在清理一些类定义。有一个类我明确地不想使用复制构造函数(让我们忽略为什么这是为了讨论),为了安全起见,我想我只是将复制构造函数定义为私有而不是实际上实现它...如果我试图在任何地方使用它会抛出编译错误。瞧,它编译得很好,但我有一个链接器错误...找不到复制构造函数实现!据推测,这意味着它在某个地方使用,但我无法找到它被使用的地方。顺便说一句,这是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

Presumably since I'm not hitting a compile error, but am hitting the linker error, that it means the class itself (or a friend) is doing the copy-constructed create (since that's all that would have access to the private constructor), but I sure can't find it!

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

6 个解决方案

#1


7  

in C++11 you can change the definition to

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

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

prior to C++11 this is usually done by inheritting from a class that declares a private copy constructor such as boost::NonCopyAble (you can simply copy this class, it's only a few lines). In this case your class (or any friends or children) also cannot access the copy constructor and it will generate a compile-time error.

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

#2


5  

Inherit from a noncopyable class:

从不可复制的类继承:

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

This works fine even if you don't have C++11 (where the delete method mentioned elsewhere is probably preferable).

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

#3


3  

What is error that linker generate? If it is LNK2019 it should be easy to track down function that uses copy constructor:

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

MSDN says that its format is:

MSDN说它的格式是:

unresolved external symbol 'symbol' referenced in function 'function'

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

If look this error message, you can find method that calls undefined copy constructor.

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

#4


1  

Are you trying to get module+line number during compilation? Try making copy-constructor templated:

您是否在编译期间尝试获取模块+行号?尝试模板化复制构造函数:

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 );
}

#5


0  

If the member is private then you should already get an error at the place of use if it doesn't have permission to access private members.

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

To get the same error in functions that do have private access you have to put the private copy-ctor declaration somewhere they don't have access to, like as a private member of a base class.

要在具有私有访问权限的函数中获得相同的错误,您必须将私有的copy-ctor声明放在他们无权访问的位置,例如作为基类的私有成员。

VS2010 doesn't support it yet, but declaring a function as deleted will also work.

VS2010尚不支持它,但声明删除的功能也可以。

#6


0  

As I recall, if you declare it inline, sometimes you'll get a compiler error that says it was declared inline but never defined. That was a while ago, and with gcc. YMMV.

我记得,如果你将它声明为内联,有时你会得到一个编译器错误,说明它是内联声明但从未定义过。那是一段时间以前和gcc。因人而异。

[Shown not to work; leaving this for posterity.]

[显示不工作;把它留给子孙后代。]

#1


7  

in C++11 you can change the definition to

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

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

prior to C++11 this is usually done by inheritting from a class that declares a private copy constructor such as boost::NonCopyAble (you can simply copy this class, it's only a few lines). In this case your class (or any friends or children) also cannot access the copy constructor and it will generate a compile-time error.

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

#2


5  

Inherit from a noncopyable class:

从不可复制的类继承:

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

This works fine even if you don't have C++11 (where the delete method mentioned elsewhere is probably preferable).

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

#3


3  

What is error that linker generate? If it is LNK2019 it should be easy to track down function that uses copy constructor:

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

MSDN says that its format is:

MSDN说它的格式是:

unresolved external symbol 'symbol' referenced in function 'function'

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

If look this error message, you can find method that calls undefined copy constructor.

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

#4


1  

Are you trying to get module+line number during compilation? Try making copy-constructor templated:

您是否在编译期间尝试获取模块+行号?尝试模板化复制构造函数:

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 );
}

#5


0  

If the member is private then you should already get an error at the place of use if it doesn't have permission to access private members.

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

To get the same error in functions that do have private access you have to put the private copy-ctor declaration somewhere they don't have access to, like as a private member of a base class.

要在具有私有访问权限的函数中获得相同的错误,您必须将私有的copy-ctor声明放在他们无权访问的位置,例如作为基类的私有成员。

VS2010 doesn't support it yet, but declaring a function as deleted will also work.

VS2010尚不支持它,但声明删除的功能也可以。

#6


0  

As I recall, if you declare it inline, sometimes you'll get a compiler error that says it was declared inline but never defined. That was a while ago, and with gcc. YMMV.

我记得,如果你将它声明为内联,有时你会得到一个编译器错误,说明它是内联声明但从未定义过。那是一段时间以前和gcc。因人而异。

[Shown not to work; leaving this for posterity.]

[显示不工作;把它留给子孙后代。]