Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 理解位复制的问题_C++_Count_Copy Constructor - Fatal编程技术网

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)