【问题标题】:Is it valid to dereference this pointer in C++?在 C++ 中取消引用这个指针是否有效?
【发布时间】:2021-06-23 03:53:19
【问题描述】:
struct myclass{
    static const int invalid = -1;
    /*explicit*/ myclass(int i, double d = 0.0){
        _var = i
    }
    int _var; 
    bool operator < (const myclass& rhs);
    bool operator > (const myclass& rhs);
    bool operator == (const myclass& rhs);
    bool operator != (const myclass& rhs);
    /*
    bool operator == (int rhs){
        return *(this) == myclass(rhs); // Is this valid C++ ?
    }
    bool operator != (int rhs){
        return *(this) == myclass(rhs); // Is this valid C++ ?
    }
    */
};

int userCodeCall() {
    myclass m(10);
    
    // Valid use Case
    if(m != myclass::invalid) {
        //.... do something
    }
    
    // Invalid use case
    if(m < 0.5) { // I want this to give me a compiler error
        //.... do something
    }
    // Invalid use case
    if(m < 5) { // I want this to give me a compiler error
        //.... do something
    }
}

我正在处理一个遗留代码库,我遇到了一个可以从 int 隐式构造的类。我发现了一个错误,我们正在执行

bool operator == (int rhs){
    return *(this) == myclass(rhs); // Is this valid C++ ?
}

我有两个问题?

  1. C++11/14/17 有效吗?

  2. 课程的设计可以改进吗?鉴于我仍然希望使用“==”比较样式来保持有效,因为它遍布用户代码库。

    if(m != myclass::invalid) // some similar API need to be supported, if not the same.
    

【问题讨论】:

  • 我把变量名弄乱了。可以说它是_var。我也在用例中使用 != 并在类中定义了 == 运算符。我在用例中需要它们。所以,假设我也在类中定义了它们。,
  • 请通过编辑问题添加所有澄清和更正,而不是离开 cmets。
  • 创建无效this 指针的唯一方法是让调用代码或以前的代码表现出未定义的行为(例如取消引用NULL、从悬空指针创建引用等)。

标签: c++ c++11 c++14


【解决方案1】:

您的解决方案很好,但是当数字类型位于右侧时,您似乎只想阻止特定的比较运算符工作。您可以通过简单地删除那些特定的运算符来做到这一点,对于除myclass 之外的所有类型。

template<typename T>
bool operator<(T) = delete;
    
template<typename T>
bool operator>(T) = delete;

【讨论】:

  • 我不仅担心 double 的隐式转换,而且还担心其他数字类型。我不希望“”将我的类类型与任何其他数字类型进行比较。我想在编译期间捕获所有这些用法。
  • @Manish 使用 SFINAE 定义一个仅对整数/浮点类型启用的模板构造函数,然后将其标记为deleted。
  • @Manish 我已经编辑了答案。现在==!= 将适用于整数类型,但&lt;&gt; 不会。
  • @cigien,我已经进一步澄清了这个问题。我想删除除==!= 之外的所有比较操作。该类派生自 boost::totally_ordered。我不确定我的陈述是否与说我只想删除 &lt;&gt; 相同。
  • @Manish 此答案中的技术与您可以用来删除任何您不想要的运算符的技术相同。如果由于继承自 boost::totally_ordered 而这对您的情况不起作用,您应该提出一个单独的问题,并且可以链接到这个问题。反复向问题添加信息可能会使现有答案无效,这并不是真正正确的做法。
【解决方案2】:

这种有效性测试更常见的习惯用法是使用显式运算符 bool:

struct myclass {
 private:
    static const int _invalid = -1;
    int _var;
 public:
    explicit myclass(int i, double d = 0.0){
        _var = i
    } 
    explicit operator bool() const { return _var != _invalid; }
    bool operator < (const myclass& rhs);
    bool operator == (const myclass& rhs);
    bool operator != (const myclass& rhs);
    bool operator > (const myclass& rhs);
};

int userCodeCall() {
    myclass m(10);
    
    // Valid use Case
    if(m) {
        //.... do something
    }
    
    // Invalid use case
    if(m < 0.5) { // gives a compile error
        //.... do something
    }
    // Invalid use case
    if(m < 5) { // gives a compile error
        //.... do something
    }
}

如果这太多了,你必须有一个 myclass::invalid 来测试,你可以让它成为类的一个实例:

static constexpr myclass invalid(-1);

【讨论】:

  • 嘿,克里斯,我已经根据您的建议继续前进。这看起来对我来说是理想的设置。
猜你喜欢
  • 2020-05-04
  • 2013-11-16
  • 2017-09-28
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多