【问题标题】:std::allocator_traits::construct with const pointer带有 const 指针的 std::allocator_traits::construct
【发布时间】:2019-07-08 20:51:33
【问题描述】:

以下代码编译良好:

#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 对象和 通过非易失性左值结果引用易失性对象 在未定义的行为中。

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

【问题讨论】:

  • 这看起来像是一个合理的骗局:stackoverflow.com/questions/42997440/…。不是 100% 确定,所以我会让你/社区来决定。
  • @NathanOliver:太好了!谢谢你。通过它阅读。
  • @NathanOliver 在初始化内存上使用placement-new是否合法似乎只是问题的一部分。 std::allocator_traits::construct()是否合法是另一部分。

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


【解决方案1】:

TL;DR:在 C++2a 之前都可以,此后std::allocator_traits&lt;std::allocator&lt;int&gt;&gt;::construct() 对传递的指针要求更高。


好吧,std::allocator_traits::construct()uses static_cast&lt;void*&gt; since it was introduced,除非分配器提供它。

虽然std::allocator::construct() 在 C++17 中已被弃用,并将在 C++2a 中删除,但它始终使用 c 样式转换。

因此,它在 C++2a 之前在语法上是有效的。


并且由于指向的对象本身不是const,因此只有通过具有该限定符访问它的指针,丢弃const并进行修改是完全合法的。

由于int 的伪dtor 是微不足道的,所以在它之上构造一个新的之前不调用它甚至都没有关系。

【讨论】:

    【解决方案2】:

    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;
    }
    

    【讨论】:

    • 请注意指针并没有被改变,它就是它所指向的那个。
    • 正如@NathanOliver 指出的那样。我只是更改了存储的值。我添加了一些stdout 来澄清这一点。
    猜你喜欢
    • 2020-03-18
    • 2013-07-25
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多