【问题标题】:How can I pass both `int` and `unsigned int` members, by reference or pointer, to the same function?如何通过引用或指针将 `int` 和 `unsigned int` 成员传递给同一个函数?
【发布时间】:2012-03-20 21:45:35
【问题描述】:

我有一个 20-30 行的 C++ 函数,它引用了 int 以进行可能的更新。现在我将传递给它的成员替换为封装更多数据的成员的成员,例如:

searchState.matchedOK = specificSearch(*pageIndices.GetStringIByRef(), searchState); //new, and overwritten.
searchState.matchedOK = specificSearch(pageOffsetInText, searchState); //old

我想将此修改本地化为上面调用的行和函数,因为一旦我验证了等价性及以上,就应该删除旧成员。

这可以通过简单的演员表实现吗?

如果你想要代码:

static bool specificSearch(int &matchLocation, const SearchSpecs &specs) {/**/}

以及最近添加的成员:

inline unsigned int *GetStringIByRef() {return &stringI;}

【问题讨论】:

  • 发布函数的新旧原型是有意义的,但通常这应该适用于 C 样式转换或static_cast
  • @STATUS_ACCESS_DENIED:我一直在函数签名(原型?)中尝试 *、&、未签名等,但都无济于事。 static_cast 只是普通C 演员不是吗?
  • 我可以将 stringI 更改为已签名,但我可能需要在稍后阶段将其 MSB 用作布尔标志。
  • 现在我们正在谈论,有了签名,这个问题就更有意义了:)

标签: c++ pointers reference casting unsigned-integer


【解决方案1】:

我不是 100% 确定我理解你的问题,所以我可能完全错过了这里的标记。但是,如果您将函数设为模板:

template<typename IntType>
static bool specificSearch(IntType &matchLocation, const SearchSpecs &specs) {/**/}

这将允许您将任一类型传递给它。

【讨论】:

  • @John:你之前实例化它的地方。问题顶部附近的两行代码应该可以正常工作,无需修改。
  • @John:取决于你如何定义“无膨胀”——如果你在两个不同的地方用两种不同的类型调用specificSearch,那么编译器将为specificSearch生成两个代码副本在二进制文件中,它们之间大约有一条指令不同。不过,这不会使源膨胀,这很好。
【解决方案2】:

您的基本问题是您的函数specificSearch 分配给int 对象。但是你想要写的是一个unsigned int 对象。幸运的是,严格的别名规则允许我们写入unsigned int,就好像它是int。类型系统并不完全鼓励它,但可以说服:

searchState.matchedOK = specificSearch(*reinterpret_cast<int*>(pageIndices.GetStringIByRef()), searchState);

这种类型依赖于被写入的值在两种类型的公共范围内(0 到INT_MAX)。我说“有点”,因为在 2 的补码系统上,写入该范围之外的值的结果与将值转换为 unsigned int 的结果相同。在非 2 的补码系统上,实际上不存在但原则上困扰着我们对可移植代码的尝试,结果是不同的,因此可能是错误的。

如果可以定义specificSearch的重载可能会更好:

static bool specificSearch(unsigned int &matchLocation, const SearchSpecs &specs) {
    int loc;
    bool retval = specificSearch(loc, specs);
    if (retval) { // I'm guessing here about the meaning of the return value
        matchLocation = loc; // converts int to unsigned int
    }
    return retval;
}

这假设包装函数可以判断“真实”specificSearch 是否分配给loc,因此它知道是否分配给matchLocation。如果调用函数无法以某种方式解决这个问题,那么这实际上不起作用(如果允许 specificSearch 分配然后抛出异常,您也需要考虑这一点)。

如果可能,将stringI 更改为正确的类型会更明智。

【讨论】:

    【解决方案3】:

    您可以使用模板来做到这一点:

    template<typename T>
    static bool specificSearch(T& matchLocation, const SearchSpecs& specs) {/**/}
    

    并分配给函数内部的matchLocation。这样,您可以使用任何可以分配给您在函数中分配给 matchLocation 的任何类型的类型。

    如果由于某种原因您不喜欢这样,并且希望它仅适用于 intunsigned int,则可以使用模板专业化:

    // leaving this undefined, which will cause a linker error if you use it with other types
    template<typename T>
    static bool specificSearch(T& matchLocation, const SearchSpecs& specs);
    
    template<>
    static bool specificSearch<int>(int& matchLocation, const SearchSpecs& specs) {
        /* definition */
    }
    
    template<>
    static bool specificSearch<unsigned int>(unsigned int& matchLocation, const SearchSpecs& specs) {
        // use the other one to avoid code duplication
        int tmp = matchLocation;
        bool retval = specificSearch(tmp, specs);
        matchLocation = tmp;
        return retval;
    }
    

    请注意,使用这些函数在intunsigned int 之间进行转换可能会收到警告,因为这两种类型的范围不同。

    【讨论】:

      【解决方案4】:

      我在这里看到了几个问题。首先,根据您的意图,最好仅按价值返回stringI。否则,您可以按如下方式调整其签名:

      inline unsigned int &GetStringIByRef() { return stringI; }
      

      为了使用 C++ 引用。

      至于

      static bool specificSearch(int &matchLocation, const SearchSpecs &specs) {/**/}
      

      你可以这样称呼它那么

      searchState.matchedOK = specificSearch(reinterpret_cast<unsigned int&>(pageIndices.GetStringIByRef()), searchState);
      

      我认为仍然取决于对象本身(如果是const)。

      如果有任何不清楚或我错过了重点,请发表评论,我会调整我的答案。

      【讨论】:

      • "从'unsigned int'类型的表达式中对'int&'类型的引用的初始化无效,现在调用specificSearch
      猜你喜欢
      • 2015-06-23
      • 2019-09-16
      • 2021-12-25
      • 1970-01-01
      • 2013-12-06
      • 2021-11-29
      • 2012-08-01
      相关资源
      最近更新 更多