2017-08-17 30 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

相关问题