【问题标题】:static_cast on custom class causes copy assignment to fail自定义类上的 static_cast 导致复制分配失败
【发布时间】:2016-09-19 18:36:30
【问题描述】:

我预计下面的程序会打印“11”,但它实际上会打印“01”,所以看起来第一个分配失败了。

struct A
{
    A(int i = 0) : i_(i) {}
    int i_;
};

int main()
{
    A x(1);
    A y;
    static_cast<A>(y) = x; // *** Fails to assign ***
    std::printf("%i", y.i_);
    y = x;
    std::printf("%i", y.i_);
}

如果我使用像int 这样的原始类型而不是A,那么int x = 1; int y; static_cast&lt;int&gt;(y) = x; 会将值1 分配给x。有什么方法可以让它适用于自定义类型?我尝试将operator A() { return *this; } 添加到struct A,但没有成功。

显然这是一个愚蠢的程序,但问题出现在我有 static_cast&lt;std::remove_const&lt;T&gt;::type&gt;(y) = x 的模板函数中,它对原始类型工作正常,但现在对自定义类型失败了。

【问题讨论】:

  • static_cast&lt;A&amp;&gt;(y)
  • std::remove_const 使用时应极度小心谨慎 - 引入未定义行为的风险很大。

标签: c++


【解决方案1】:

与任何演员表一样,static_cast&lt;A&gt;(y)y 的临时副本。您可以改为转换为引用类型 (static_cast&lt;A&amp;&gt;(y));更一般地说,您可以使用std::add_lvalue_reference 来实现这一点。

对于你描述的更具体的例子,你需要const_cast而不是static_cast,但基本原理是一样的。

这里是an example that compiles, but has UB,因为修改了const 对象(因此返回0,而不是42)。在不知道更多关于你想要做什么的情况下,我不会为了这个例子的目的而试图掩饰这一点:

#include <iostream>
#include <type_traits>

template <typename T>
T foo(T val)
{
    T x{};

    using not_const = typename std::remove_const<T>::type;
    using ref_type  = typename std::add_lvalue_reference<not_const>::type;

    const_cast<ref_type>(x) = val;

    return x;
}

int main()
{
    std::cout << foo<const int>(42) << '\n';
}

【讨论】:

  • 谢谢你说得通。但是,如果值只分配给临时副本,为什么它对原始类型有效?
  • 但是int x = 1; int y = 0; static_cast&lt;int&gt;(y) = x; std::cout &lt;&lt; y; 打印出1
  • @GeorgeSkelton:不,它没有。它甚至不能编译,至少不能在符合标准的 C++ 编译器中编译。点击我刚刚给你的链接进行现场演示。
  • 好吧,刚刚看到你的代码。我正在使用 VS,它没有给我警告并且似乎“工作”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
相关资源
最近更新 更多