6

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

#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:关键字时,代码会编译,但永远不会调用复制 ctor。那么为什么它在私有时会出错呢?

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

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

6 回答 6

5

您正在从临时初始化引用。
标准规定:
临时应初始化(8.5.3 par 5)“使用非参考副本初始化规则(8.5)”。

临时删除复制结构(标准允许。12.8 par 5)。
但是,标准明确指出(12.2 par 1):
“即使避免创建临时对象(12.8),也必须遵守所有语义限制,就像创建临时对象一样。[示例:即使复制构造函数没有被调用,所有的语义限制,例如可访问性(第 11 条),都应该被满足。]"

(另外,在寻找正确的报价时,发现了这个重复的:)

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

于 2009-10-13T16:45:17.793 回答
4

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

于 2009-10-13T15:48:36.943 回答
3

假设您发布的代码是项目中唯一的代码,并且在任何地方都没有按值隐蔽传递 Foos,我所能想到的就是 gcc 正在优化

Foo foo;
foo = Foo();

Foo foo = Foo();

...这是不合理的,因为第一种形式是默认构造和赋值,而第二种等效于

Foo foo(Foo());

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

一般来说,不同保护级别的赋值运算符和复制构造函数并不是一个好主意。如您所见,结果可能不直观。

于 2009-10-13T15:42:25.493 回答
1

在以下情况下调用 Copy Tor:

  1. 通过值将对象作为参数传递给函数,
  2. 从函数返回一个对象。

因此,您肯定会在代码中的某处执行其中一种或两种情况。您应该将 Copyctor 设置为 public 或避免前面的 2 种情况。

于 2009-10-13T15:38:29.433 回答
0

如果您编写,将调用复制构造函数

Foo foo; // normal constructor
Foo foo1(foo); //copy constructor

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

于 2009-10-13T15:39:31.100 回答
-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使用复制构造函数创建)

于 2009-10-13T15:49:56.253 回答