2017-08-17 33 views
1

我有一個微不足道的分配器:C++:哪些構造函數在向量中調用<int> vn {MyAllocator <int>(a)}?

// alloc.h 
#include <cstdlib> 
#include <new> 
#include <iostream> 

template <class T> 
struct Mallocator { 
    typedef T value_type; 
    Mallocator() { 
     std::cout << "default ctor is called" << std::endl; 
    } 
    template <class U> Mallocator(const Mallocator<U>&) { 
     std::cout << "copy ctor is called" << std::endl; 
    } 
    T* allocate(std::size_t n) { 
    std::cout << "Mallocator::allocate(size_t n) is called, n = " << n << " "; 
    if(n > std::size_t(-1)/sizeof(T)) throw std::bad_alloc(); 
    if(T *p = static_cast<T*>(std::malloc(n*sizeof(T)))) { 
     std::cout << "return p = " << std::hex << (uintptr_t)p << std::dec << std::endl; 
     return p; 
    } 
    throw std::bad_alloc(); 
    } 
    void deallocate(T* p, std::size_t n) { 
     std::cout << "Mallocator::deallocate(T *p, size_t n) is called, p = " << std::hex << (uintptr_t)p << std::dec << " n = " << n << std::endl; 
     std::free(p); 
    } 
}; 
template <class T, class U> 
bool operator==(const Mallocator<T>&, const Mallocator<U>&) { return true; } 
template <class T, class U> 
bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { return false; } 

這是客戶機代碼(只有一個的ABC使用):

#include "alloc.h" 
#include <vector> 
#include <iostream> 
using namespace std; 

int main() { 
    Mallocator<int> a; 
    cout << "---instantiate---" << endl; 
    // vector<int, Mallocator<int>> v(a);     // A 
    vector<int, Mallocator<int>> v{Mallocator<int>(a)}; // B 
    // vector<int, Mallocator<int>> v(Mallocator<int>(a)); // C 
    cout << "---push_back(1)---" << endl; 
    v.push_back(1); 
    cout << "---push_back(2)---" << endl; 
    v.push_back(2); 
    cout << "---push_back(3)---" << endl; 
    v.push_back(3); 
    cout << "---push_back(4)---" << endl; 
    v.push_back(4); 
    cout << "---push_back(5)---" << endl; 
    v.push_back(5); 
    cout << "---exiting---" << endl; 
} 

輸出,不管AB是總是這樣:

default ctor is called 
---instantiate--- 
---push_back(1)--- 
// omitted for brevity.. 

我的問題

(1)如果A存在,分配器只構造一次,這是可以理解的。但是,當存在B而不是A時,顯然Mallocator的複製構造函數在B中調用,但輸出並未反映此情況。爲什麼?

(2)如果B存在,哪個構造函數std::vector被調用?在這個reference中,唯一帶有初始化列表的構造函數看起來不像這樣。如果我用C而不是B,它不會編譯,鐺++的錯誤信息是沒有幫助..

Eidt:我知道這個分配器是微不足道,但它不是這個問題的要點..

「alloc.h」的代碼是從頁面末尾的here改編而來的。

回答

3

1)你的「拷貝構造函數」不是一個。真正的拷貝構造函數不是一個模板。如果不自行聲明一個類,則每個類都會獲得隱式聲明的拷貝構造函數。 Mallocator<int>沒有聲明一個真正的拷貝構造函數,所以你得到隱式聲明併爲你定義。由於你的類是空的,那個拷貝構造函數什麼都不做,並且什麼都不打印(並且,由於重載解析規則,選擇了將分配器複製到你的構造器模板上)。

2)如果沒有初始化列表構造函數是可行的,則列表初始化可以調用非初始化列表構造函數。 B最終調用與A相同的構造函數。您的C的一個案例。

+0

是的,沒錯,雖然修復了這個代碼(從U中移除模板),但它仍然不會調用複製構造函數的副作用。或者,更好的說,_maybe_不會打電話。 – Swift

+1

@Swift你會看到vector的參數至少有一個拷貝到它存儲的分配器。這不是可以消除的。 –

+0

這是不容置疑的。實際上,我看到兩個好奇的(8)並不是在這種情況下可以調用的正確構造函數。 – Swift

相關問題