我正在測驗使用以下小代碼初始化類成員的不同模式:
struct S {
S() { std::cout << "ctor\n"; }
S(const S&) { std::cout << "cc\n"; }
S(S&&) noexcept{ std::cout << "mc\n"; }
S& operator=(const S&) { std::cout << "ca\n"; return *this; }
S& operator=(S&&) noexcept{ std::cout << "ma\n"; return *this; }
~S() { std::cout << "dtor\n"; }
};
struct P1 {
S s_;
};
struct P2 {
P2(const S& s) : s_(s) {}
S s_;
};
struct P3 {
P3(const S& s) : s_(s) {}
P3(S&& s) : s_(std::move(s)) {}
S s_;
};
int main() {
S s;
std::cout << "------\n";
{
P1 p{s}; // cc
}
std::cout << "---\n";
{
P1 p{S{}}; // ctor = copy elision
}
std::cout << "------\n";
{
P2 p{s}; // cc
}
std::cout << "---\n";
{
P2 p{S{}}; // ctor cc
}
std::cout << "------\n";
{
P3 p{s}; // cc
}
std::cout << "---\n";
{
P3 p{S{}}; // ctor mc
}
std::cout << "------\n";
}
正如您在評論中看到的那樣,只有在P1{S{}}復制省略的聚合初始化發生并且我們的類在沒有任何復制/移動建構式呼叫的情況下被初始化的情況下。我想知道是否可以提供一個像聚合初始化器一樣直接初始化成員的建構式。任何的想法?
更新: 我想知道我是否對標準的理解有誤,但根據我的理解,這里發生了一些奇怪的事情:
- 對于初始化串列,我們有:
class-or-identifier ( expression-list(optional) ) :使用直接初始化或如果 expression-list 為空,則初始化由 class-or-identifier 命名的基類或成員
- 對于直接初始化,我們有:
如果 T 是型別別,如果初始值設定項是型別與 T 相同的類的純右值運算式(忽略 cv 限定),則初始值設定項運算式本身,而不是從中實作的臨時物化,用于初始化目標物件。(復制省略)
因此,我認為對于像s_(std::move(s))復制省略這樣的初始化串列應該發生,不是嗎?
uj5u.com熱心網友回復:
我想知道是否可以提供一個像聚合初始化器一樣直接初始化成員的建構式。
當然。撰寫一個不接受成員型別引數的建構式,而是接受轉發給成員建構式的引數。在您的情況下,成員型別是默認可構造的,因此您不需要轉發任何引數:
struct P4 {
P4(): s() {}
S s;
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/413469.html
標籤:
上一篇:角度路線引數為空
