簡體   English   中英

類成員不是引用,而是帶有通過引用傳遞參數的構造方法

[英]Class Member Not a Reference but Constructor with Argument Passed by Reference

當您在C ++中遇到類似的情況時會發生什么:

class foo {
public:
   foo(obj &b);
   obj a;
};

foo::foo(b) : a(b) {}

b內的值是否復制到a 或者因為b為參考,那么的參考b被分配到a

這與以下代碼相同:

void foo(obj& b) {
    obj a(b);
}

它將b對象復制(復制構造)到a

在類定義中

class foo {
   foo(obj &b);
   obj a;
};

數據成員a不是參考。 因此,在此構造函數中,數據成員由b引用的對象的值初始化。

foo::foo(b) : a(b) {}

另一方面,如果將類定義為

class foo {
   foo(obj &b);
   obj &a;
};

然后在此構造函數中a是一個引用

foo::foo(b) : a(b) {}

a將引用b依次引用的對象。

您正在查看一個構造函數初始化器列表 ,該列表

指定直接和虛擬基礎子對象以及非靜態數據成員的初始化程序

編輯:

在內部,此簡單的復制構造 a ,它將在class obj定義為: obj(obj&)obj(const obj&)

如果obj 沒有用戶定義的構造函數,則編譯器將隱式聲明一個復制構造函數該拷貝構造函數將:

使用直接初始化,以其初始化順序對對象的基礎和非靜態成員執行完整的成員方式副本。

發生復制時obj & b允許傳遞對對象的引用,以保存副本。

但是,在構造函數中,效果為obj a = b; 調用obj上的副本構造函數。

考慮一下代碼:

obj o;
foo f(o);

調用foo::foo ,參數通過引用傳遞,因此o 不會復制到參數b 接着:

foo::foo(b) : a(b) {}

由於成員變量a未定義為引用,因此b將被復制到a ,即將調用obj的副本ctor。

在某些時候,我進入了一些測試程序的便捷git repo並拉出了我的對象生命周期跟蹤器:

#include <iostream>
#include <string>

using namespace std;

struct A {
    A()
    {
        cout << "Created " << describe() << endl;
    }

    A(A&& r)
    : ident(r.ident)
    {
        r.zombie = true;
        cout << "Move-constructed " << describe() << endl;
    }
    A(const A& r)
    {
        cout << "copy-constructed " << describe() << " from " << r.describe() << endl;
    }
    ~A() {
        cout << "destroyed " << describe() << endl;
    }

    A& operator=(A&& r) {
        cout << describe() << " is being move-assigned from " << r.describe() << endl;
        ident = r.ident;
        zombie = false;
        r.zombie = true;
        return *this;
    }
    A& operator=(const A&r ) {
        cout << describe() << " is being assigned from " << r.describe() << endl;
        zombie = false;
        return *this;
    }

    string describe() const {
        return (zombie ? "zombie "s : "object "s) + to_string(ident);
    }

    size_t ident = next_ident();
    bool zombie = false;

    static size_t next_ident() {
        static size_t ident = 0;
        return ident++;
    }
};


class foo {
public:
    foo(const A &b) : a(b) {}
    foo(A &&b) : a(move(b)) {}
    A a;
};

auto main() -> int
{
    A a;
    foo f(a);
    foo f2(move(a));
    A a2;
    f = a2;
    f2 = move(a2);

    return 0;
}

示例輸出:

Created object 0
copy-constructed object 1 from object 0
Move-constructed object 0
Created object 2
copy-constructed object 3 from object 2
object 1 is being move-assigned from object 3
destroyed zombie 3
Move-constructed object 2
object 0 is being move-assigned from object 2
destroyed zombie 2
destroyed zombie 2
destroyed object 2
destroyed object 3
destroyed zombie 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM