我怎样才能找到 C++ 的位置?通过编译错误使用复制构造函数?

发布于 2024-12-29 09:18:25 字数 744 浏览 2 评论 0原文

简而言之:是否有某种方法可以修改类定义,使其无法在复制构造函数的使用点处进行编译,无论它在何处使用?

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

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

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?

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

半暖夏伤 2025-01-05 09:18:25

在 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 (你可以简单地复制这个类,只有几个线)。在这种情况下,您的类(或任何朋友或孩子)也无法访问复制构造函数,并且它将生成编译时错误。

in C++11 you can change the definition to

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.

慵挽 2025-01-05 09:18:25

从不可复制的类继承:

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 方法可能更可取),这也可以正常工作。

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).

蝶舞 2025-01-05 09:18:25

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

MSDN说它的格式是:

函数“function”中引用的外部符号“symbol”无法解析

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

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

MSDN says that its format is:

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

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

梦幻之岛 2025-01-05 09:18:25

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

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

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 );
}
望笑 2025-01-05 09:18:25

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

要在具有私有访问权限的函数中出现相同的错误,您必须将私有复制器声明放置在它们无权访问的位置,例如作为基类的私有成员。

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

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.

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

我们的影子 2025-01-05 09:18:25

我记得,如果您将其声明为内联,有时您会收到编译器错误,指出它被声明为内联但从未定义。那是不久前的事了,和 gcc 一起。 YMMV。

[显示不工作;留给后人。]

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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文