Open Nwpuer opened 8 years ago
ex13.39(实现StrVec)中的alloc为什么不像书上那样声明为static成员呢?
13.5 章节里 StrVec
类的定义中,没把 alloc
声明为 static 啊。你指的是哪里的定义?
另外,为什么要声明为 static 呢?
我在实现ex16.16(将StrVec实现为模板)时,发现将alloc声明为非static成员会编译通过,而如果将它声明为static的话,VS2013会提示“无法解析的外部符号”,能不能解释一下为什么?
方便贴出代码吗?
。。难道书不一样?我的是《C++ Primer》第五版中文版。在我的书上13.5章节中StrVec的定义中,关于alloc的定义是这样的:static std::allocator<std::string> alloc;
而且应该不需要每个StrVec对象中都有一个alloc成员吧,将它定义成static从而与类直接相关比较好。
ex16.16是这样的:
template <typename T> class Vec { ...... private: static std::allocator<T> alloc; ...... }
有static的话会提示“无法解析的外部符号”,去掉static的话会运行成功。会不会是VS2013不支持该特性?
关于为什么static一定要类外定义,上面的链接解释的不错.
是否一定要做成static
变量, 我针对这个问题讨论一下, 有不对的地方各位指正下.
c++表中中对内存的分配, 提供了std::allocator<T>
, cppref上面查看内容就知道, 这个标准定义的内存分配类实际的内存分配和释放都是通过成员函数来实现的(allocate
和deallocate
), 只要想使用那必须得有个对象, 这也就是为什么LZ声明成static
对象的原因, 因为这个对象又没状态啥的, 每一个类对象都存一个std::allocator岂不浪费?
那么,问题是一定要搞成static
么? 未必
实际上如果不写容器类(并且自己搞定内存),std::allocator基本上也用不到, 我们来看一下SGI STL里面容器类是怎么定义的,以list为例,类的片段:
template <class T, class Alloc = alloc>
class list {
protected:
typedef void* void_pointer;
typedef __list_node<T> list_node;
typedef simple_alloc<list_node, Alloc> list_node_allocator;
protected:
link_type get_node() { return list_node_allocator::allocate(); }
得到几点结论:
return list_node_allocator::allocate();
是个静态函数函调, 没有使用任何对象.没看过vs的STL咋实现的,是不是也提供了一个自己的内存分配类且提供了静态函数.
如果是,那么直接替换掉allocator的使用,可以规避掉非要声明个static对象了
如果不是, 自己实现一个内存分配类好了, SGI STL最终也不过是调用了malloc
而已.
// alloc类内部实现, 提供了静态函数
static void * allocate(size_t n)
{
void *result = malloc(n);
if (0 == result) result = oom_malloc(n);
return result;
}
另外, c++11提供了allocator_traits, 提供了allocate
的静态方法,可以调用,不过这个方法还是需要传递Alloc实例对象的,搞不清楚它存在的意义是啥.
// std::allocator_traits::allocate
static pointer allocate( Alloc& a, size_type n );
统一回复一下上面那几位:中文版有 static
是翻译者私自加上的,英文版没有。
@ender233
首先,SGI STL 的源码是 C++ 7的,非常非常古老。如果为了学习钻研,可以借鉴,但平心而论,其意义不大了。不如花时间去读 CppCoreGuidelines.
std::allocator
,因为那时候压根没这个。StrVec
的 alloc
为例,声明为 static
看似节省了空间,但破坏了对象的"粒度",这个成员成了一个"全局共享池",你甚至不清楚它会什么时候回收内存。其次,这一点点空间,压根没有必要节省,每个对象保证自己的 alloc
受自己控制,而不会和别的对象搅和到一起,这一点对于代码的清晰度来讲,是十分必要的。其次,你提到 VS, 而它恰恰就是用你后来提到的 allocator_traits
实现。不仅 MS, 几乎所有现代编译器(G++, Clang) 都用这个来实现。
以下截自 Visual Studio 2017:
而 VS 有没有像你们猜测的那样,使用静态成员变量呢?其实并没有:
当然,这里的实现要比书上的例子复杂太多,所以情况不可一概而论。譬如这里的 _Compressed_pair
其实用到了将要进入标准的 range
库,未来容器的实现,恐怕都会像这个方向靠拢。
really make sense!
首先,SGI STL 的源码是 C++ 7的,非常非常古老。如果为了学习钻研,可以借鉴,但平心而论,其意义不大了
习惯了套路还是能看懂的,其他版本我看的有点晕. SGI早起的版本继承比较少,新的SGI各种继承也复杂。SGI还是可以入门看看的。
ex13.39(实现StrVec)中的alloc为什么不像书上那样声明为static成员呢? 我在实现ex16.16(将StrVec实现为模板)时,发现将alloc声明为非static成员会编译通过,而如果将它声明为static的话,VS2013会提示“无法解析的外部符号”,能不能解释一下为什么?