[英]C++ vector member initialization
我對下面關於Test
中的vec
的程序中的 output 感到困惑。 為什么它是大小為 100 而不是 1 的向量? 我認為std::vector<T> var{a}
與std::vector<T> var = {a}
相同。
#include <iostream>
#include <vector>
using namespace std;
struct Value {
int a;
int b;
};
class Test {
public:
std::vector<struct Value> vec{100};
};
class Test2 {
public:
std::vector<int> vec{100};
};
int main()
{
Test test;
std::cout << "test size: " << test.vec.size() << std::endl;
Test2 test2;
std::cout << "test2 size: " << test2.vec.size();
return 0;
}
Output:
test size: 100
test2 size: 1
std::vector
有一個帶有std::initializer_list<T>
參數的構造函數。 當使用像{100}
這樣的初始化列表時,如果適用,此構造函數將始終優先。
對於std::vector<int>
,初始化器{100}
與std::initializer_list<int>
兼容,因此將使用構造函數。 它將創建一個包含集合{100}
的向量,該集合是一個值為100
的int
。
對於std::vector<Value>
初始化器{100}
與std::initializer_list<Value>
參數不兼容。 Value
沒有用於將int
轉換為Value
的轉換構造函數,因此您無法從{100}
構造std::initializer_list<Value>
。 您可以驗證此示例不允許進行此轉換。 編譯器將嘗試采用較低優先級的構造函數,並將使用初始化 100 個默認構造Value
的構造函數。
如果您添加一個Value::Value(int)
構造函數或使用{{100}}
作為Test2
的初始值設定項,您會發現std::vector<Value>
現在將只包含一個元素。 在這兩種情況下,初始化列表都可以轉換為std::initializer_list<Value>
並且現在將使用該構造函數。
當您發現{100}
的含義時, T == int
的變化。
簡要回答你的問題:
vector<Value>{100}
100
的 100 不能解釋為Value
,因此大小構造函數優先。
如果你堅持, {100}
可以解釋為Value
,所以你可能需要一個額外的花括號, vector<Value>{ {100} }
。
請參閱此處的插圖: https://godbolt.org/z/xcMT1oc5z
為了避免進一步討論合法性,我的建議如下:
為了保持跨類型的含義,初始化大小初始化一致的括號和元素的括號,這迫使你這樣做:
std::vector<int> vec = std::vector<int>(100);
一般來說:
std::vector<T> vec = std::vector<T>(100);
在這種情況下,大小始終為100
。
這可能不是一個完全有用的答案,但我決定在 STD 庫中 vector 的 class 聲明中放置一個斷點。
在 vector 的定義中,它有 3 種處理賦值的方式。 一個結構將提供一個值構造,其中一個 int 將被分配為一個大小范圍構造。
它讀取std::vector<struct> vect{100};
構建長度為 100 的向量,而std::vector<int> vect{100};
行為類似vect.insert(v.end(),100);
這是根據for傳入的object的類型。
為了提供信息,最后一個選項是采用給定值,並將其分配給多個點。 因此,如果您有 100 個“x”,它會將“x”放入您的向量中 100 次。
我從中學到的是,有一點你的向量需要一個 size_type 輸入和一個 _Valty&& 輸入(我還不知道那是什么。稍后會查找它)並提供 3 個不同 args 之間的構造。
我最好的猜測是您的結構正在填充 1-args 路徑並充當長度聲明,而 int 作為本機類型落入 2-args 路徑並充當值賦值。
sizeof(Value) 可能 == 0,而 int 的大小將為 1。
編輯:我猜是 1 和 2(或 _Count == 0,並且 Count == 1),但是我錯了。 它是 _Count == 0 和 _Count == 2。這非常有趣。
template <class... _Valty>
_CONSTEXPR20 void _Construct_n(_CRT_GUARDOVERFLOW const size_type _Count, _Valty&&... _Val) {
// Dispatches between the three sized constructions.
// 1-arg -> value-construction, e.g. vector(5)
// 2-arg -> fill, e.g. vector(5, "meow")
// 3-arg -> sized range construction, e.g. vector{"Hello", "Fluffy", "World"}
auto& _Al = _Getal(); //////////////// For test1, _Count is 100, for test2, _Count is 1;
auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al);
auto& _My_data = _Mypair._Myval2;
_Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data);
if (_Count != 0) {
_Buy_nonzero(_Count);
_Tidy_guard<vector> _Guard{this};
// This one happens with a struct
if constexpr (sizeof...(_Val) == 0) {
_My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al);
} else
if constexpr (sizeof...(_Val) == 1) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_Valty..., const _Ty&>);
_My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val..., _Al);
} else
// This one happens with an int
if constexpr (sizeof...(_Val) == 2) {
_My_data._Mylast = _Uninitialized_copy(_STD forward<_Valty>(_Val)..., _My_data._Myfirst, _Al);
} else {
static_assert(_Always_false<_Ty>, "Should be unreachable");
}
_Guard._Target = nullptr;
}
_Proxy._Release();
}
真正有趣的是,它似乎是在分配分配器引用時發生的。 我絕不是這門語言的專家,但我真的很想弄清楚這個難題! 感謝您提出有趣的挑戰!
如果您以前從未瀏覽過 class 的定義,我建議您嘗試一下。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.