如果需要禁止一个类的拷贝(多鉴于RAII的资源类),按习惯我们会把拷贝构造函数和赋值运算符重载设置为私有的。比如:

class Base
{
  public:
    Base (int a)
    {
      cout <<"construct"<<endl;
    }
    virtual ~Base (){}

  private:
    Base(const Base& b)
    Base & operator=(const Base& b)
};

int main(int argc, const char *argv[])
{
  Base b(1);//ok
  Base c=1;//error[1]
  Base d=c;//error
  c = d;//error
  return 0;
}

但是问题在于[1]这里没有道理被屏蔽掉,应该会被优化成Base c(1)。如下代码可以证明:

class Base
{
  public:
    Base (int a)
    {
      cout <<"construct"<<endl;
    }
    virtual ~Base ()
    {
    }
    Base(const Base& b)
    {
      cout<<"copy consturct" <<endl;
    }
};

int main(int argc, const char *argv[])
{
  Base c=1;
  return 0;
}

运行结果:

construct

后来我试了一下才发现,首先这个优化是编译器层面的,所以不同的编译器处理应该是不一样的,虽然我们见到的编译器应该都支持。其次这个优化不是语法检查前做的,也就意味着,在构造函数没有被声明为explicit的时候,语法检查会把这个认为是先做了类型转换,然后调用拷贝构造函数,也就是如下:

Base c = Base(1);

这就在编译的时候报错了。

本文版权归CXH_ME所有,原创不易,人艰不抄,转载还请注明出处,谢谢