请告诉我堆栈和堆之间的区别与下面的代码
int main()
{
int arr[3];
int *a;
arr [5] = 6; // out of bound but it will not give error.
arr [3000] = 8 ; //SIGSEGV
a = malloc (sizeof (int));
a[4] = 6;
a[4000] = 8; //No error
}
Run Code Online (Sandbox Code Playgroud)
我知道arr是一个静态数组,当我执行arr [3000]时会访问其他进程的地址,这会给出SIGSEGV错误.但我不明白为什么[4000]不会给我任何运行时错误,即SIGSEGV信号.
谢谢
如何std::vector分配对象?它似乎只是std::allocator::allocate用来创建一块内存,但从来没有调用过std::allocate::construct.这是真的?难道std::vector只分配内存,从来没有构造对象的内存分配?
如果没有默认构造函数怎么办?当对象上没有默认构造函数时,构造函数是如何调用的?如果有多个参数怎么办?
例如,使用此代码没有默认构造函数,std :: allocator允许它.
#include <vector>
using namespace std;
class A{
protected:
int m;
public:
explicit A(int a) : m(a) { }
};
int main(){
vector<A> test;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试实现我自己的符合标准的链表,但我似乎无法弄清楚为什么你会想要一个 T 分配器。在我的实现中,节点类保存 T 本身,而不是指向存储在内存中其他位置的 T 的指针,因此 T 永远不会被显式分配,而是只作为节点的一部分创建。我会理解为什么你可能想要一个节点分配器,但为什么是 T?
我的节点的简化版本在这里。
class Node {
Node* next, prev;
T data; // Not T*
}
Run Code Online (Sandbox Code Playgroud) 标准草案 N4618 是这样说的std::pmr::monotonic_buffer_resource:
Run Code Online (Sandbox Code Playgroud)bool do_is_equal(const memory_resource& other) const noexcept override;返回:
this == dynamic_cast<const monotonic_buffer_resource*>(&other)
换句话说,标准不只是将指针与 进行比较,而是this == &rhs希望供应商不遗余力地使用dynamic_cast右手指针。
我想不出任何理智的情况dynamic_cast会改变比较的结果。不过,我可以想到一些疯狂的案例:
class new_delete_memory_resource : public memory_resource {
void *do_allocate(size_t bytes, size_t align) override {
return ::operator new(bytes, align);
}
void *do_deallocate(void *p, size_t bytes, size_t align) override {
::operator delete(p, bytes, align);
}
bool do_is_equal(const memory_resource& rhs) const noexcept override {
return (this == &rhs);
}
};
class TwoHeadedResource …Run Code Online (Sandbox Code Playgroud) 在容器中具有这些特征的原因是什么(https://en.cppreference.com/w/cpp/memory/allocator_traits)
propagate_on_container_copy_assignment Alloc::propagate_on_container_copy_assignment if present, otherwise std::false_type
propagate_on_container_move_assignment Alloc::propagate_on_container_move_assignment if present, otherwise std::false_type
propagate_on_container_swap Alloc::propagate_on_container_swap if present, otherwise std::false_type
Run Code Online (Sandbox Code Playgroud)
is_always_equal(since C++17) Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type
Run Code Online (Sandbox Code Playgroud)
我知道容器实现在分配和交换的实现中会以一种或另一种方式表现。(并且处理这些情况是可怕的代码。)我也明白有时人们可能需要将移动容器保持在一种状态resizeble或者至少可以调用一些最后的释放,因此分配器不能无效。(我个人认为这是一个弱论点。)
但问题是, 为什么这些信息不能成为自定义分配器类型本身的正常实现和语义的一部分?
我的意思是,容器复制分配可以尝试复制分配源分配器,如果语法复制分配没有真正复制,那么,就像说你的容器没有 propagate_on_container_copy_assignment。
以同样的方式而不是使用 is_always_equal一个实际上可以使分配器分配什么也不做。
(此外,如果is_always_equal为真,则可以让operator==分配器返回std::true_type以发出信号。)
在我看来,这些特征似乎试图覆盖可以通过普通 C++ 方式提供给自定义分配器的语义。这似乎与泛型编程和当前的 C++ 哲学背道而驰。
唯一的原因,我认为这对于实现与“旧”容器的某种向后兼容性很有用。
如果我今天要编写一个新容器和/或一个新的非平凡分配器,我可以依靠分配器的语义而忘记这些特征吗?
在我看来,只要移动的分配器可以“解除分配”一个空指针状态(这意味着在这种特殊情况下主要是什么都不做),那么它应该没问题,如果resize抛出,那也很好(有效) ,这只是意味着分配器无法再访问其堆。
编辑:实际上, 我可以这样简单地编写容器吗?并将复杂性委托给自定义分配器的语义?:
templata<class Allocator>
struct my_container{
Allocator alloc_;
...
my_container& operator=(my_container const& other){ …Run Code Online (Sandbox Code Playgroud) allocator move-semantics copy-assignment c++11 move-assignment-operator
C++ 分配器。我知道 String 将分配一个new内部实现的块缓冲区,并在析构函数中释放它(调用 delete[])。
我的问题是使用时是否会免费加倍allocator<string>?
另外,string的buffer地址是否和allocate(n)region相同?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main(int argc, char **argv)
{
const int cnt = 10;
allocator<string> alloc;
auto p = alloc.allocate(cnt);
alloc.construct(p);
for (int i = 0; i < cnt; ++i)
{
cout << p+i << endl; // print buffer address
}
alloc.destroy(p); // will it free buffer of string?
alloc.deallocate(p, cnt); // will it free buffer of string again? …Run Code Online (Sandbox Code Playgroud) C ++ 20除去construct()和destruct()成员std::allocator。我应该如何构造通过 分配的对象std::allocator<T>::allocate()?我发现了std::uninitialized_fill()and std::uninitialized_copy(),但据我所知,它们不是分配器感知的,它们会进行复制,我认为这会对非 POD 类型的性能造成很大影响。
下面的代码片段(参见 Godbolt)表明大分配器不会增加 STL 容器的内存占用,但大比较器会。为什么会这样?
// compiled with x86-64 gcc 10.3, -std=c++17
#include <functional>
#include <iostream>
#include <memory>
#include <set>
struct MyLess : public std::less<int>
{
char dummy[1024];
};
struct MyAllocator : public std::allocator<int>
{
char dummy[1024];
};
int main()
{
std::cout << sizeof(std::set<int, MyLess>) << std::endl; // prints 1064
std::cout << sizeof(std::set<int, std::less<int>, MyAllocator>) << std::endl; // prints 48
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我知道它仅在 std::allocator 中被弃用和删除。我可以在我自己的分配器上实现它。但为什么它被弃用了呢?
我想创建一个大的 std::vector所以operator[]应该收到long long而不是unsigned int,我尝试编写自己的分配器:
template <typename T>
struct allocator64 : std::allocator<T> {
typedef long long difference_type;
typedef unsigned long long size_type;
};
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试以下内容时:
long long n = 5;
std::vector<int, allocator64<int> > vec(n);
vec[n-1] = 2;
Run Code Online (Sandbox Code Playgroud)
我收到第二行和第三行的以下警告:
警告C4244:'argument':从'__int64'转换为'unsigned int',可能会丢失数据
我错过了什么?我认为operator[]大小构造函数的类型和来源应该来自allocator::size_type.
我正在使用VS9(2008).