当私有拷贝构造函数带有公共赋值运算符时出错

发布于 2024-08-07 02:57:43 字数 1015 浏览 6 评论 0原文

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

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

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

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

Can one of you explain why the following piece of code does not compile?

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

The error I receive:

$ 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

Note: when I remove the private: keyword the code compiles but the copy ctor is never called. So why does it err when it's private?

Not sure if it's important but I'm using:

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

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

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

发布评论

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

评论(6

情感失落者 2024-08-14 02:57:43

您正在初始化临时引用。
标准规定:
应“使用非引用复制初始化规则 (8.5)”来初始化临时对象(8.5.3 第 5 部分)。

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

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

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

You are initializing a reference from temporary.
The standard states:
The temporary should be initialized (8.5.3 par 5)"using the rules for a non-reference copy initialization (8.5)".

The copy construction is removed for the temporary (permitted by the standard. 12.8 par 5).
However, the standard clearly states (12.2 par 1):
"Even when the creation of the temporary object is avoided (12.8), all the semantic restrictions must be respected as if the temporary object was created. [Example: even if the copy constructor is not called, all the semantic restrictions, such as accessibility (clause 11), shall be satisfied. ]"

(also, when looking for the right quote, found this duplicate :)

Edit:
adding relevant location from the standard

少女净妖师 2024-08-14 02:57:43

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

That code compiles with gcc 4.3.3 and 4.4.1. Maybe that's just a bug in gcc 4.1?

反话 2024-08-14 02:57:43

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

Foo foo;
foo = Foo();

......

Foo foo = Foo();

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

Foo foo(Foo());

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

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

Assuming that the code you've posted is the only code in the project, and there's no covert passing of Foos by value going on anywhere, all I can figure is that gcc is optimizing

Foo foo;
foo = Foo();

to

Foo foo = Foo();

...which is unsound, as the first form is a default-construct and an assignment, while the second is equivalent to

Foo foo(Foo());

...which is clearly a copy construction. If I'm right, the copy constructor is not being run because GCC can optimize away the redundant temporary; this is permitted by the C++ spec.

In general, it is not a good idea to have assignment operators and copy constructors at different protection levels; as you've seen, the results can be unintuitive.

心房敞 2024-08-14 02:57:43

Copy Ctor 在以下情况下被调用:

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

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

Copy Ctor is called when:

  1. passing an object by value as parameter to a function,
  2. returning an object from a function.

So you are certainly doing one or both of these case somewhere in your code. You should set Copy Ctor as public or avoid the 2 previous cases.

垂暮老矣 2024-08-14 02:57:43

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

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

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

Copy constructor would be called if you write

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

In your case, first the default constructor is called and then the operator= method.

一江春梦 2024-08-14 02:57:43
#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 是使用复制构造函数创建的)

#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
}

Check this, in Foo f2=f1; ( f2 is created using copy constructor)

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