【发布时间】:2014-07-04 17:15:47
【问题描述】:
我开始感到不舒服,如果为了编译一些简单的代码我必须向尊敬的听众提出 4 个问题。但根据我的经验,自定义分配器参数似乎是最困难的。 我已经定义了一个非常非常简单的自定义分配器。 我有一个 typedef Char 可能是 char,char16_t,char32_t 。
我定义了一个作为 basic_string 实例化的字符串。
我定义了该类的实例,代码正确地将它们分配到自定义内存(名为 m 的数组 - 您可以在调试器中看到它)。
该代码适用于各种尺寸。通过阅读basic_string的代码和查看内存排列,可以理解basic_strings的实例只是指向已分配内存的指针。
我也将 Vector 定义为:vector<Char>。
问题在于,有时向量会节省自定义内存,而有时则不会。是错误还是我不懂基本概念?
Vector vv={U'a',U'b',U'c',U'd',U'e',U'f',U'g',U'h'}; // doesn't assigns nothing
vv[0]=U'a'; // works correctly
vv[1]=U'b'; // works correctly
for(size_t i=0;vv0[i];i++)
vv.push_back(vv0[i]); // doesn't assign nothing.
整个代码如下:
//#include <bits/c++config.h>
//#define _GLIBCXX_FULLY_DYNAMIC_STRING 1
//#include <stdint.h> //#include <stddef.h> //#include <memory>
#include <iostream>
#include <string>
#include <limits>
#include <vector>
#define CONCAT_PURE(a,b,c) a ## b ## c
#define CONCAT(a,b,c) CONCAT_PURE(a,b,c)
typedef char char8_t; typedef char char64_t; // just for symmetry, char64 may exist when tokens are 64bit.
#define charSz 32 // may be 8,16,32,64 change by hand !
typedef CONCAT(char,charSz,_t) Char; // may be char8_t or char16_t or char32_t or char64_t
// the macro STR(xxxxx) permits us to write strings with characters of 8 bit 16 bit 32 bit (later on 64 bits)
#if charSz == 8
#define STR(s) #s
#elif charSz == 16
#define STR(s) u ## #s
#elif charSz == 32
#define STR(s) U ## #s
#elif charSz == 64
#define STR(s) UU ## #s
#endif
typedef int32_t Token;typedef unsigned char byte;
typedef size_t addr;addr freePos=0;Token freeT=0;
const size_t heapSize=0x400;byte m[heapSize];
addr Allocate(size_t sz){addr t=freePos;freePos+=sz;return t;} // justs increasing
void Deallocate(addr p,size_t sz){/**((size_t*)(m+p))=sz;*/} // not important actually
template <typename T>
struct Allocator {
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
typedef T value_type;
typedef T* pointer; typedef const T* const_pointer;
typedef value_type& reference; typedef const value_type& const_reference;
typedef std::size_t size_type; typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind{typedef Allocator<U> other;};
// The initialization of freePos and freeT is done independently of the class definition because doing
// it in the class creator another instance (with other template parameter would reinitialize them.
Allocator() {}
~Allocator() {}
template<typename U> Allocator(U){}
static inline pointer allocate(size_type n){return (pointer)(m+Allocate(n*sizeof(T)));}
static void deallocate(pointer p, size_type n){Deallocate((byte*)p-m,sizeof(T)*n);}
inline size_type max_size() const{return std::numeric_limits<size_type>::max() / sizeof(T);}
inline void construct(pointer p, const T& t) {}
inline void destroy(pointer p) {}
};
template <typename T>
bool operator==(Allocator<T> const &, Allocator<T> const &) { return true; }
template <typename T>
bool operator!=(Allocator<T> const &, Allocator<T> const &) { return false; }
typedef std::basic_string< Char,std::char_traits<Char>,Allocator<Char> > String;
typedef std::vector< Char,Allocator<Char> > Vector;
int main(){
// fill memory with values in order to be able to see modifications
for (size_t i=0;i<sizeof(m);i++) m[i]=0xDD;
String s;
String t;
String u;
s=STR(nice);
t=STR(very beautyfull);
u=STR(good);
Char vv0[]=U"looking_well";
Vector vv={U'a',U'b',U'c',U'd',U'e',U'f',U'g',U'h'};
vv[0]=U'a';
vv[1]=U'b';
for(size_t i=0;vv0[i];i++)
vv.push_back(vv0[i]);
return 0;
}
【问题讨论】:
-
您能否添加一些痕迹,以便我们可以看到预期和实际结果/副作用?请注意,
std::string通常使用小字符串优化,其中对于短字符串,不使用分配器。 -
@dyp 我一开始就解释过了。当你写: Vector vv={U'a',U'b',U'c',... } 你期望上面的值会进入 Vector 但他们不会。内存指针得到了正确处理,但没有写入任何内容。取而代之的是 vv[0]=U'a' 可以正常工作,并且 vv[1]=U'b' 也可以正常工作。相反, vv.push_back 正确处理分配和指针,但不向内存写入任何内容。如果您需要更详细的信息,请告诉我具体该怎么做。
-
你的
construct没有构造,它什么都不做。因此向量元素的初始化失败。 -
@dyp 通常?
g++和clang似乎没有实现它,因为sizeof(std::string)与sizeof(char *)相同。 -
如果你实现
construct,这符合我的预期。
标签: c++ memory-management