簡體   English   中英

C++ 向量成員初始化

[英]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}的向量,該集合是一個值為100int

對於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.

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