C++ 理解位复制的问题
我试图理解以下代码:C++ 理解位复制的问题,c++,count,copy-constructor,C++,Count,Copy Constructor,我试图理解以下代码: blueberry bitCopy(blueberry a) { cout << "bitCopy " << blueberry::blQuantity << endl; return a; } void howMany() { cout << blueberry::blQuantity << endl; } int main() { blueberry firstBl; howMany()
blueberry bitCopy(blueberry a) {
cout << "bitCopy " << blueberry::blQuantity << endl;
return a;
}
void howMany() {
cout << blueberry::blQuantity << endl;
}
int main() {
blueberry firstBl;
howMany();
bitCopy(firstBl);
howMany();
}
我希望最后是0,而不是-1。有人能解释一下吗
请不要告诉我我需要一个复制构造函数。我没有试图修复此代码以使对象计数正常工作。相反,我试图理解这是如何工作的,以及为什么blQuantity不是我期望的值
类blueberry只是一个具有静态int值blQuantity的类,该值在每次创建对象时在构造函数中递增,在每次对象超出范围时在析构函数中递减
你确定每次都是这样吗?我想你错过了一些东西
blueberry bitCopy(blueberry a)
这是传递值;i、 例如,blueberry a
这是提交给bitCopy()
的内容的副本。这将调用蓝莓的,您尚未定义它。因此,编译器为您创建了一个简单的对象,它从原始对象复制任何成员值,但不增加任何内容。如果需要,您必须定义:
blueberry::blueberry (const blueberry&) // copy constructor
blueberry& operator= (const blueberry&) // copy assignment operator
您可能还需要一个移动构造函数和移动赋值操作符——请参阅维基百科关于“三(或五)规则”的文章
我在上面一段中提到了这一点
之所以blQuantity
最后是-1,是因为实际上有两个使用bitCopy()
制作的副本,一个用于参数,一个用于返回值。如果将其更改为:
blueberry bitCopy (blueberry &a)
也就是说,通过引用传递,只有一份副本,blQuantity
之后将为0。如果随后使返回值void
,则不会生成副本,blQuantity
应为1
这里演示了复制构造函数和
操作符=
(复制赋值操作符)的角色:
第一行来自A(“#1”)
。最后三行是ab=测试(a)
的结果。第一个是复制参数,A test(testa)
。第二个是创建返回值,它是参数的副本,因此对象上的标记现在是#1-copy-copy
。在main()中初始化b
。当退出test()
时,参数对象被销毁,1-复制一个再见代码>
复制分配:
分配(#1[=])
这来自main()
中的b=a
请注意,b
的早期版本未被销毁。这是因为副本分配旨在将一个对象转换为另一个对象的副本;两个对象都没有被销毁,但目标对象的内容可能已经更改,因此b
的标记现在是#1[=]
。可以预见:
正在退出。。。
#1[=]再见!
#再见!
当程序结束时,a
和b
将被销毁
如果将test()
的签名更改为:
A& test (A &a)
您将获得以下输出:
A con(#1)
测试()
一份(1份)
副本分配:
分配(#1[=])
退出。。。
#1[=]再见!
#再见!
只创建了两个对象,a
通过构造函数和b
通过copy con;直到最后,它们才被摧毁。如果不使用test()
的返回值,则只会创建一个对象。请不要使用void main
发布代码。你能修好吗?谢谢。您没有向我们展示足够的代码,但我猜您也在减少析构函数中的计数(因此期望为零),而不是在复制构造函数中增加计数(因此,当函数参数被销毁时会额外减少,而在复制局部变量创建时不会增加匹配的增量)。如果你想要一个好的答案,你应该发布一篇文章,解释为什么你期望得到你期望的东西。而且,这不是“抄袭”,不管你是什么意思。这只是常规的对象复制。在析构函数中,你是否正在减少blQuantity
…@MichaelAndroidNewbie:如果你想让其他用户收到你的评论,你必须在他们的用户名前加一个“@”,就像我刚才做的那样。否则,默认情况下,仅通知您正在评论的问题或答案的作者。也就是说,1)你还没有显示析构函数(它是blQuantity--
?)和2)试着一步一步地描述你期望计数器何时增加/减少,以及为什么。这样的话,答案会更准确。谢谢你提供的有用信息。我真正想要的是对正在发生的事情的解释。我知道,要使对象计数在这种情况下工作,我需要一个复制构造函数。但是,我想了解当前形式的代码中发生了什么好的——您创建了一个blueberry
并检查blQuantity
,它现在是1,因为它在构造函数中是递增的。然后调用bitCopy()
,它使用编译器定义的复制构造函数创建一个新的蓝莓,该构造函数不增加任何内容,因此blQuantity
仍然是1。关于RVO有一点我认为我错了(编辑了最后一段)——编译器没有优化返回值,返回值也是一个副本,因此生成了两个副本,两个副本都被销毁了,因此最终得到-1。如果创建副本con并包含一些输出,通过调用bitCopy()
,您可以看到制作了两个副本。谢谢,这非常有帮助!因此,为了检查一下,如果我将第二个blueberry设置为等于bitCopy(firstBl)的输出,编译器会在之后销毁临时返回变量吗?如果使用blueberry x=bitCopy(firstVl)
,它不会立即销毁,因为副本将是x
。如果您编写copy con来生成一些输出(“blueberry copied!”),并在t中为每个blueberry提供某种类型的id字符串
blueberry bitCopy (blueberry &a)
#include <iostream>
#include <string>
using namespace std;
class A {
public:
string x;
A (string s) : x(s) {
cout << "A con " << "(" << x << ")\n";
}
A (const A& other) : x(other.x) {
x.append("-copy");
cout << "A copy " << "(" << x << ")\n";
}
A& operator= (const A& other) {
x = other.x;
x.append("[=]");
cout << "A assign " << "(" << x << ")\n";
return *this;
}
~A () { cerr << x << " A bye!\n"; }
};
A test (A a) {
return a;
}
int main (void) {
A a("#1");
cout << "test()\n";
A b = test(a);
cout << "Copy assign:\n";
b = a;
cout << "Exiting...\n";
return 0;
}
A& test (A &a)