std :: allocator_traits ::用const指针构造

时间:2019-07-08 20:51:33

标签: c++ c++11 c++14 language-lawyer allocator

以下代码可以正常编译:

#include <iostream>
#include <memory>
int main()
{
const int * a = new int(5);

std::cout << *a << std::endl; // Prints 5

// *a = 5; // Compiler error.
using at = std::allocator_traits<typename std::allocator<int>>;
auto alloc = std::allocator<int>();
at::construct(alloc, a);

std::cout << *a << std::endl; // Prints 0
}

libstdc ++可以实现

::new((void*)a) int;

但是aconst

这是未定义的行为吗?还是新放置的位置不算作修改? 我修改了*a的值const。据我了解,这是不允许的:

  

通过非常量访问路径修改const对象,并   通过非易失性glvalue结果引用易失性对象   处于不确定状态。

https://en.cppreference.com/w/cpp/language/const_cast

2 个答案:

答案 0 :(得分:4)

TL; DR :很好,直到C ++ 2a,此后std::allocator_traits<std::allocator<int>>::construct()将对传递的指针有更高的要求。


好吧,std::allocator_traits::construct() uses static_cast<void*> since it was introduced,除非分配器提供了它。

尽管std::allocator::construct()在C ++ 17中已弃用,而在C ++ 2a中将被删除,但它始终使用c样式的强制转换。

因此,从语法上讲,直到C ++ 2a才有效。


由于指向的对象本身不是const,因此只有通过具有该限定符,抛弃const并进行修改才可以访问它的指针。

由于int的伪dtor是微不足道的,因此甚至不需要在它之上构造一个新的伪dtor就被调用。

答案 1 :(得分:0)

const int* a指定a所指向的内存插槽中包含的值是常量,而不是指针本身。

#include <memory>

int main()
{
    const int * a = new int;

    a = nullptr; // Compile fine
    *a = 1; // Won't compile

    return 0;
}

您希望代码的行为类似于:

#include <memory>

int main()
{
    int* const a = new int;

    a = nullptr; // Won't compile
    *a = 1; // Compile fine

    return 0;
}