亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

請問在C ++ 11和Boost.Container下vector :: resize

請問在C ++ 11和Boost.Container下vector :: resize

C++
楊魅力 2019-11-03 04:04:58
我有一個C ++ 03應用程序,其中std::vector<T>類型始終用作臨時緩沖區。因此,通常會使用std::vector<T>::resize()來調整它們的大小,以確保它們足夠大以在使用前容納所需的數據。該函數的C ++ 03原型實際上是:void resize(size_type n, value_type val = value_type());因此實際上在調用時resize(),通過添加適當數量的拷貝來擴大向量val。但是,通常,我只需要知道它vector足夠容納我所需的數據即可。我不需要將其初始化為任何值。復制構造新值只是浪費時間。C ++ 11可以解決(我認為):在其規范中,它分為resize()兩個重載:void resize(size_type n); // value initializationvoid resize(size_type n, const value_type &val); // initialization via copy這很符合C ++的哲學:只為您想要的付出。但是,正如我指出的那樣,我的應用程序不能使用C ++ 11,因此當我遇到Boost.Container庫時就感到很高興,該庫在其文檔中指出了對該功能的支持。具體來說,boost::container::vector<T>實際上有三個重載resize():void resize(size_type n); // value initializationvoid resize(size_type n, default_init_t); // default initializationvoid resize(size_type n, const value_type &val); // initialization via copy為了驗證我是否了解所有內容,我快速進行了一次測試以驗證C ++ 11 std::vector<T>和的行為boost::container::vector<T>:#include <boost/container/vector.hpp>#include <iostream>#include <vector>using namespace std;namespace bc = boost::container;template <typename VecType>void init_vec(VecType &v){    // fill v with values [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]    for (size_t i = 0; i < 10; ++i) v.push_back(i);    // chop off the end of v, which now should be [1, 2, 3, 4, 5], but the other 5 values    // should remain in memory    v.resize(5);}g++在C ++ 03模式下使用4.8.1進行編譯,如下所示:g++ vectest.cc./a.out產生以下輸出:std: 0 1 2 3 4 0 0 0 0 0 boost: 0 1 2 3 4 0 0 0 0 0 boost w/default: 0 1 2 3 4 5 6 7 8 9這并不奇怪。我希望C ++ 03 std::vector<T>用零初始化最后的5個元素。我什至可以說服自己為什么boost::container::vector<T>要這樣做(我會假設它模仿C ++ 03模式下的C ++ 03行為)。當我明確要求默認初始化時,才得到想要的效果。但是,當我以C ++ 11模式重建時,如下所示:g++ vectest.cc -std=c++11./a.out我得到以下結果:std: 0 1 2 3 4 0 0 0 0 0 boost: 0 1 2 3 4 0 0 0 0 0 boost w/default: 0 1 2 3 4 5 6 7 8 9一模一樣!這導致了我的問題:在這種情況下,我應該從三個測試中看到相同的結果,這是我的錯嗎?這似乎表明std::vector<T>接口更改并沒有真正起任何作用,因為resize()在前兩種情況下,最后一次調用中添加的5個元素仍然用零初始化。
查看完整描述

3 回答

?
HUWWW

TA貢獻1874條經驗 獲得超12個贊

因此,實際上,在調用resize()時,通過添加適當數量的val副本來擴大向量。但是,通常,我只需要知道向量足夠大即可容納我需要的數據。我不需要將其初始化為任何值。復制構造新值只是浪費時間。


不,不是。擁有實際上沒有構造的元素的容器是沒有意義的。我不確定您希望看到的不是零。未指定/未初始化的元素?這不是價值初始化的意思。


如果您需要N個元素,那么您應該有N個正確構造的元素,這就是需要的std::vector::resize。值初始化將使對象初始化為零,而沒有默認構造函數可調用,因此,實際上這與您想要的相反,安全性和初始化程度較低,而不是更多。


我建議你真正想要的是std::vector::reserve。


這似乎表明std::vector<T>界面更改并未真正起任何作用


它肯定會產生作用,但不是您要尋找的那個。新的resize重載是為了方便起見,因此當您只需要默認或什至值初始化時,您就不必構造自己的臨時文件。這不是容器工作方式的根本變化,而是它們始終持有有效的?類型的?實例。


?有效,但如果您離開它們,則處于未指定狀態!



查看完整回答
反對 回復 2019-11-04
?
慕村9548890

TA貢獻1884條經驗 獲得超4個贊

還有就是用C ++ 11個小功能上的差異resize簽名,但您的測試不會揭露它。考慮類似的測試:


#include <iostream>

#include <vector>


struct X

{

    X() {std::cout << "X()\n";}

    X(const X&) {std::cout << "X(const X&)\n";}

};


int

main()

{

    std::vector<X> v;

    v.resize(5);

}

在C ++ 03下打?。?/p>


X()

X(const X&)

X(const X&)

X(const X&)

X(const X&)

X(const X&)

但是在C ++ 11下它會打?。?/p>


X()

X()

X()

X()

X()

進行此更改的動機是為了更好地支持中的不可復制(僅移動)類型vector。在大多數情況下,包括您的情況在內,此更改都沒有影響。


有一種方法可以通過使用自定義分配器(您的編譯器可能支持或可能不支持)來完成C ++ 11中的目標:


#include <iostream>

#include <vector>


using namespace std;


template <class T>

class no_init_alloc

    : public std::allocator<T>

{

public:

    using std::allocator<T>::allocator;


    template <class U, class... Args> void construct(U*, Args&&...) {}

};



template <typename VecType>

void init_vec(VecType &v)

{

    // fill v with values [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    v.resize(10);

    for (size_t i = 0; i < 10; ++i) v[i] = i;  // Note this change!!!

    // chop off the end of v, which now should be [1, 2, 3, 4, 5], but the other 5 values

    // should remain in memory

    v.resize(5);

}


template <typename VecType>

void print_vec(const char *label, VecType &v)

{

    cout << label << ": ";

    for (size_t i = 0; i < v.size(); ++i)

    {

        cout << v[i] << ' ';

    }

    cout << endl;

}


int

main()

{

    std::vector<int, no_init_alloc<int>> std_vec;

    init_vec(std_vec);

    std_vec.resize(10);

    print_vec("std", std_vec);

}

哪個應該輸出:


std: 0 1 2 3 4 5 6 7 8 9 

在no_init_alloc簡單地拒絕做任何初始化,這是罰款int,有一個未確定的值離開它。我不得不更改您init_vec使用賦值來初始化而不是使用構造。因此,如果您不小心,可能會很危險/令人困惑。但是,它的確避免了不必要的初始化。



查看完整回答
反對 回復 2019-11-04
  • 3 回答
  • 0 關注
  • 428 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號