问题 如何正确施放? (或者我应该这样做?)


如果我有代码如

class CString { int GetLength(); };

bool smaller(CString s1, std::string s2) {
    return s2.size() > s1.GetLength();
}

对我来说最好的事情是什么?

  • 更改 s1.GetLength() 至 (size_t)c.GetLength()
    这将有助于摆脱关于“签名 - 无符号不匹配”的编译器警告,并传达我的演员意图,并且是迄今为止最简单的路线。但它可能不赞成。 :(

  • 更改 s1.GetLength() 至 static_cast<size_t>(c.GetLength())
    这将有助于摆脱警告,与“正确”类型的演员。

  • 更改 s1.GetLength() 至 static_cast<std::string::size_type>(c.GetLength())
    它非常冗长......这种抽象是否有实际的好处,或者我应该打破它?

  • 保持原样?
    这将有助于编译器使用。进行溢出检查 /RTCc 开关 (我主要担心的是这里),以警告为代价。

  • 做点别的吗?
    我应该制作自己的演员版吗?使用宏?我应该在运行时和编译时检查吗?还有其他想法吗?

编辑:

似乎这个例子的字面意思太过分了......

我显然不是故意说话 只是 关于 CString::GetLength()。这种特殊方法当然不是我的一大担心。 :)我担心的是更多 一般 当我得到一个永远不会的整数时 应该 是消极的,但是哪个 可以 从理论上讲,由于错误。

哎呀,我可能会 写作 执行此操作的方法,以覆盖另一段代码 - 所以我无法更改签名。我的代码肯定会有错误,即使我不指望它。

在这种情况下,我该怎么办?


11548
2018-04-05 08:54


起源

我肯定会远离最后一个,可能会与第一个一起。其他人似乎对此很啰嗦。 - Luchian Grigore
你的意思是 s2.size()? - Default
更改 GetLength() 返回一个 size_t? - hmjd
它有意义吗? GetLength() 在这种情况下返回负值? - juanchopanza
@Default:啊,我这样做,错字;谢谢。 - Mehrdad


答案:


你能改变吗? GetLength()?从根本上说,问题是长度永远不会消极,而无符号类型反映的是最好的。长度不应用a测量 int

但除此之外,所有三种解决方案都是相同的。 std::string::size_type 总是 std::size_t,虽然我会用 static_cast,在这种情况下,C风格的演员阵容执行相同的演员表。因为你知道返回的长度永远不会消极(顺便说一句,确保这一点;你永远不知道人们会做些什么奇怪的事情),你完全安全,只需要输入类型:

return s2.size() > static_cast<std::size_t>(s1.GetLength());

如果 CString::GetLength  能够 由于某种原因,你应该决定如何将这种转换从负面变为正面。截短?幅度(绝对值)?无论你需要什么。


如果你担心错误,要么做一个明确的检查并抛出异常(取决于你的域,这可能是太昂贵),或使用 assert。但是,一般来说,您应该信任该文档。


6
2018-04-05 08:58



所以你的意思是我应该完全忽略它的好处 /RTCc 在这里(在调试模式下)?这似乎很有帮助......(不,我无法改变它 - 它在预先编写的库中,例如ATL / WTL / MFC。) - Mehrdad
我假设 CString 来自Windows MFC。 - Peter Wood
@Mehrdad:如果检查很重要,我会自己添加,而不是依赖于特定的编译器功能。如果 GetLength() 永远不会消极,然后只是随心所欲。不会有任何数据丢失。 - GManNickG
@GManNickG:帮助我找到错误只是“重要”,而不是“重要”,因为如果代码已经正确,它就会发生。 - Mehrdad
@Mehrdad:我真的不明白。如果 GetLength() 永远不会消极,然后转换为无符号类型的相等(或更大)位大小永远不会导致数据丢失。 std::size_t 肯定是那么大 int,所以你完全安全地做演员表,不需要任何检查。 - GManNickG


将演员阵容放在自己的功能中,并注释:

std::string::size_type size(const CString& mfcString)
{
    // CString::GetLength is always non-negative
    // http://msdn.microsoft.com/en-us/library/aa300471(v=vs.60).aspx

    return static_cast<std::string::size_type>(mfcString.GetLength());
}

然后你的代码将是:

bool smaller(const CString& s1, const std::string& s2)
{
    return size(s1) < s2.size();
}

4
2018-04-05 09:18



在我看来,这是迄今为止最好的答案。在处理一个简洁的API时,不要乱用你的代码。相反,为包装提供一个封闭和隐藏丑陋的干净界面。纯粹的应用 干 原理。 - Matthieu M.
我的回答是正确的。 :( +1 - GManNickG


我会说正确的解决方案是改变签名 CString::getLength() 返回无符号类型。鉴于您按价值获取参数,您可能需要考虑为其提供转换构造函数 CString 拿一个 std::string (或者你应该改变你的函数的签名来获取它的参数 const&)。

就个人而言,我认为操作是转换而不是转换,并将其写为:

return std::string::size_type(s1.getLength())
    < s2.size();

2
2018-04-05 09:06



演员 是 转换。你只是改变演员表示法,他们是 完全相同。 - GManNickG
我很清楚 T(x) 和 static_cast<T>(x) 等同于编译器。然而,有意的记法可以向人类读者传达信息:还有其他地方,例如我正在使用的向下转换(在相应的隐式转换之后) static_cast<T*>(x) 引起注意这一事实,这不只是修补一个隐含的转换。 - Dietmar Kühl


更改方法CString :: getLength()并返回无符号类型。

尝试这个

return std :: string :: size_type(s1.getLength())     <s2.size();


0
2018-04-05 11:33