使用公共赋值运算符的私有副本ctor时出错

时间:2009-10-13 15:32:22

标签: c++ copy-constructor assignment-operator

你们其中一个人可以解释为什么以下代码不能编译吗?

#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
private:
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo foo;

  foo = Foo();
}

我收到的错误:

$ g++ -o copy_ctor_assign copy_ctor_assign.cc && ./copy_ctor_assign
copy_ctor_assign.cc: In function 'int main()':
copy_ctor_assign.cc:10: error: 'Foo::Foo(const Foo&)' is private
copy_ctor_assign.cc:17: error: within this context

注意:当我删除 private: 关键字时,代码会编译,但永远不会调用copy ctor。那么为什么它是私有的呢?

不确定它是否重要,但我正在使用:

$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
Copyright (C) 2006 Free Software Foundation, Inc.

6 个答案:

答案 0 :(得分:5)

您正在初始化临时参考 标准规定:
临时应该初始化(8.5.3参数5)“使用非参考拷贝初始化(8.5)的规则”。

临时删除复制结构(标准允许.12.8标准杆5) 但是,该标准明确规定(12.2标准1):
“即使避免创建临时对象(12.8),也必须尊重所有语义限制,就像创建临时对象一样。[例如:即使没有调用复制构造函数,所有语义限制,例如可访问性(第11条),应予以满足。]“

(同样,在寻找正确的引用时,发现这个duplicate:)

编辑: 从标准中添加相关位置

答案 1 :(得分:4)

该代码使用gcc 4.3.3和4.4.1编译。也许这只是gcc 4.1中的一个错误?

答案 2 :(得分:3)

假设您发布的代码是项目中唯一的代码,并且没有任何隐藏的Foos按值传递,我可以想象的是gcc正在优化

Foo foo;
foo = Foo();

Foo foo = Foo();

...这是不健全的,因为第一种形式是默认构造和赋值,而第二种形式相当于

Foo foo(Foo());

......这显然是一个复制结构。如果我是对的,则不会运行复制构造函数,因为GCC可以优化冗余临时;这是C ++规范允许的。

通常,将赋值运算符和复制构造函数置于不同的保护级别并不是一个好主意;如你所见,结果可能不直观。

答案 3 :(得分:1)

在以下情况下调用复制Ctor:

  1. 将值作为参数传递给函数,
  2. 从函数返回一个对象。
  3. 因此,您肯定会在代码中的某处执行其中一个或两个案例。您应该将Copy Ctor设置为公共或避免前两种情况。

答案 4 :(得分:0)

如果你写

,就会调用复制构造函数
Foo foo; // normal constructor
Foo foo1(foo); //copy constructor

在您的情况下,首先调用默认构造函数,然后调用operator = method。

答案 5 :(得分:-1)

#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo f1;// default constructor called

  Foo f2 = f1; //copy constructor called
}

Foo f2=f1;f2使用复制构造函数创建)

中选中此项