我正在为类型数组实现资源分配克隆操作T.直接实现后使用从源到新数组new T[sz]的std::copy调用.它走两次记忆.
我想分配原始内存然后使用,std::uninitialized_copy所以出于性能原因我只会走一次内存.我知道如何在使用自定义分配器(Allocator.allocate后跟std::uninitialized_copy)时完成此操作,并且我知道如何使用std::allocator(在规范的第20.4.1.1节中使用::operator new以下内容lib.allocator.members).我担心的是,std::allocator对于已经定义的类型T,基于a 的方法似乎是错误的T::operator new.我知道我可以使用Boost.TypeTraits来检测这种情况has_new_operator.
是否有一种简单的,符合标准的方式来分配并初始化原始内存,以一种尊重被覆盖的新方式(并且仅仅通过内存一次)?如果没有,使用SFINAE在一个实现使用std::allocator和一个使用被覆盖的运算符new 之间调度似乎是合理的吗?FWIW,通过Boost进行掠夺并没有显示出这种特性的使用has_new_operator.
谢谢,里斯
我正在使用Howard Hinnant很好的基于竞技场的小分配器,short_alloc.
让我感到震惊的是,从一个已经超出其竞技场并因此在堆上分配的向量进行移动分配可以使用通常的快速移动分配(即,抓取目标的资源)来完成.然而,这种情况并非如此:
typedef arena<16> arena_type;
typedef short_alloc<int, 16> alloc_type;
typedef std::vector<int, alloc_type> vec_type;
arena_type arena1, arena2;
vec_type vec1(alloc_type(arena1)), vec2(alloc_type(arena2));
vec1.resize(100);
void* data = vec1.data();
vec2 = std::move(vec1);
assert(vec2.data() == data); // fails
Run Code Online (Sandbox Code Playgroud)
正如在这个答案中所解释的,这是由于向量的移动赋值运算符比较了两个分配器(注意propagate_on_container_move_assignment就是这样std::false_type).由于两个分配器不比较相等(因为它们具有不同的竞技场),目标向量需要分配内存并逐个移动值.
通过将等于运算符更改为,可以实现所需的行为
template <class T1, size_t N1, class T2, size_t N2>
bool operator==(const short_alloc<T1, N1>& x, const short_alloc<T2, N2>& y) noexcept
{
return N1 == N2 && (&x.a_ == &y.a_ || y.a_.on_heap());
}
Run Code Online (Sandbox Code Playgroud)
其中,on_heap()如果分配没有使用它的竞技场检查.
这个解决方案看起来相当hackish(注意例如,平等不对称),我可以/我会通过这样做射击自己吗?有优雅的解决方案吗?
在你阅读之前: const_reference是typedef,不需要const T&像你看到的那样std::vector<bool>::const_reference = bool.请在阅读其他内容时牢记这一点,以便正确理解它(如值得一提的,这对很多人来说很难).
我想将STL容器用于简单类型(例如int)并发现它们使用次优的const T& "反模式" - 它适用于大类,但对于简单/基本类型而言,如果不内联则是次优的 - 考虑嵌入式系统,例如在ARM/ATSAM4L上,具有实例化.
问题是:为什么例如从C++ 11开始vector::push_back重新设计参数(const value_type&)而不是(Allocator::const_reference)?对于泛型应该是相同的allocator,但是以另一种方式执行它将帮助我为基本类型编写自定义分配器(或模板特化),这将定义const_reference为类型本身(请参阅参考资料vector<bool>::const_reference = bool).
问题2:是否有适合我的适配器类?
像这样的东西:
template<class T, class base = std::vector<T> >
class myvect: protected base {
public:
typedef T const_reference;
void push_back(const_reference value) {
base::push_back(value); }}
Run Code Online (Sandbox Code Playgroud)
最终用法将是这样的:
typedef void (*action_t)(void*,int);
extern "C" void work(void *, action_t);
work(&vect, (action_t)&vect::push_back);
Run Code Online (Sandbox Code Playgroud)
(注意:忽略以前代码块中可能存在的转换问题,希望你有这个想法.) …
我有两个问题:
1)是否可以实现使用alloca在堆栈上分配内存的分配器,否则符合C++ STL?
如果那里有代码,只需将我指向URL即可让我高兴.:-)如果那里没有代码,也许你可以草拟函数allocate和deallocate?
2)如果对上述问题的回答为"是",我想了解如何为类成员在堆栈上分配内存.举个例子,考虑一下
std::vector<int, AllocaAllocator<int> >
Run Code Online (Sandbox Code Playgroud)
并且假设对该向量的成员函数'resize'的调用首先调用'deallocate'然后'分配'分配器.
调用allocate的范围是成员函数resize的范围.这是不是意味着在该函数调用结束时从堆栈中删除了已分配的内存?
亲切的问候,Bjoern
看着向量,我意识到在创建向量时我从未使用过第二个参数.
std::vector<int> myInts; // this is what I usually do
std::vector<int, ???> myOtherInts; // but is there a second argument there?
Run Code Online (Sandbox Code Playgroud)
看看上面的链接,它说它适用于:
要使用的分配器对象而不是构造新的对象.
或者,对于这个:
分配器:用于定义存储分配模型的分配器对象的类型.默认情况下,使用类型T的allocator类模板,它定义了最简单的内存分配模型,并且与值无关.
我想这与内存管理有关.但是,我不知道如何使用它.
有关于此的任何指示?
有以下代码段错误的明显原因吗?
#include <vector>
#include <emmintrin.h>
struct point {
__m128i v;
point() {
v = _mm_setr_epi32(0, 0, 0, 0);
}
};
int main(int argc, char *argv[])
{
std::vector<point> a(3);
}
Run Code Online (Sandbox Code Playgroud)
谢谢
编辑:我在linux/i686上使用g ++ 4.5.0,我可能不知道我在做什么,但是因为甚至以下的段错误
int main(int argc, char *argv[])
{
point *p = new point();
}
Run Code Online (Sandbox Code Playgroud)
我真的认为它必须和对齐问题.
在阅读有关C++和标准库的书籍时,我看到频繁引用分配器.
例如,Nicolai Josuttis的C++标准库在最后一章中详细讨论了它们,并且第2项("了解分配器的约定和限制")和11("理解自定义分配器的合法用途")在Scott Meyers的有效的STL是关于它们的使用.
我的问题是,分配器如何代表一个特殊的内存模型?默认的STL内存管理不够吗?何时应该使用分配器?
如果可能,请使用简单的内存模型示例进行说明.
使用稍加修改的版本霍华德Hinnants的C++ 11堆栈分配这是记录在这里,并在这里,与std::basic_string和编译与gcc被使用libstdc++,下面的例子(见直播):
const unsigned int N = 200;
arena<N> a;
short_alloc<char, N> ac(a) ;
std::basic_string<char,std::char_traits<char>,short_alloc<char, N>> empty(ac);
Run Code Online (Sandbox Code Playgroud)
出现以下错误(以及其他错误):
error: no matching function for call to 'short_alloc<char, 200ul>::short_alloc()'
if (__n == 0 && __a == _Alloc())
^
Run Code Online (Sandbox Code Playgroud)
但是在编译clang和使用时它可以正常工作libc++(请参见实时).
该stdlibc++实施std::basic_string预计分配器有一个默认的构造函数.
C++ 11是否要求分配器是默认的可构造的?哪种实施是正确的?
在C++标准库分配内存的大多数地方,用户可以通过提供满足Allocator要求的类来自定义它.例如,几乎所有容器都接受一个allocator模板参数,并std::allocate_shared返回一个shared_ptr包含的元素和控制块都通过提供的Allocator分配.
但是,标准库可以(可能)分配内存的地方有一些,但是没有Allocator提供支持.我能想到的是:
std::make_unique()(没有相应的allocate_unique())std::anystd::function (分配器支持将在C++ 17中删除)std::valarraystd::basic_filebuf(虽然std::basic_stringbuf 不使用分配器)std::inplace_merge()问题:
::operator new,plain new还是未指定的内存源?any并将其从中删除的原因是function什么?成员函数的文档std::allocator<T>::allocate在 ( [allocator.members] ) 中说:
\n\n备注:数组的存储是通过调用 \xe2\x80\x8b
\n::\xe2\x80\x8boperator new([new.delete]) 获得的,但未指定该函数的调用时间和频率。该函数启动数组对象的生命周期,但不启动任何数组元素的生命周期。
我想知道为什么它说::operator new而不只是operator new?双冒号有什么区别吗?operator new如果省略了双冒号,这里可以调用哪个其他的?