【问题标题】:Explicit string behavior in non-constructor member functions非构造函数成员函数中的显式字符串行为
【发布时间】:2012-12-31 08:05:36
【问题描述】:

我希望我的问题标题正确。

我有一个非常大/旧的数据库,其中包含许多非空终止字符数组和一些 std::string 类型。我正在创建一个将使用该数据库的工具,并且我想确保它对于非空终止字符数组的安全性。理想情况下,我希望同时支持这两种类型,以便开发人员轻松使用该工具。

void AddCell( const std::string & _cell_str );
void AddCell( const char * _cell_data, size_t _array_size );

但是,有一个特定的场景可能会出现问题:如果新开发人员不知道 char 数组是非空终止的并且出于懒惰决定使用 std::string 的隐式转换,因为他没有必须输入数组大小,那么 std::string 可能会显示一些不需要的字符。

我该如何处理这个问题?我应该强迫某人指定 std::string 的长度吗?我应该只删除 std::string 重载函数并让每个人都从他们的 std::string 中使用 c_str() 吗?理想情况下,我只使用显式关键字,但它仅适用于构造函数。我犹豫要不要使用 std::string。

【问题讨论】:

  • 我在这里缺少一些基本的东西。什么是 std::string 的隐式转换?你指的是AddCell("example");吗?
  • @ahenderson,std::string 的构造函数接受 char* 并且不是显式的。
  • @MarkRansom 感谢您的澄清。我仍然希望我有一个他们试图避免的行为的例子。
  • 我现在很清楚了。如果有人输入 text 其中const char text[] 然后我们有UB,如果数组不是空终止的。

标签: c++


【解决方案1】:

您可以更改第一个重载,以便不采用 std::string 引用,而是采用对您创建的具有从 std::string 的隐式转换的新类型的引用。所以你不会看到来自 const char* 的隐式转换,但会毫无问题地使用 std::string。

【讨论】:

  • 这种新类型也可以有一个构造函数,它接受一个char 数组,并通过一些模板魔法自动包含数组大小。那么你只需要一个版本的成员函数。
  • 您能否阐明隐式转换 from 到 std::string 的含义?你只是说它应该有一个接受 const std::string 引用的参数吗?那样的话,我不是还是和现在一样的问题吗?不应该是明确的吗?
【解决方案2】:

有不同的事情可以做。其中之一是delete-ing const char* 重载:

void AddCell(const std::string&);
void AddCell(const char*) = delete;
void AddCell(const char*,size_t);

将函数标记为delete 会在使用时触发编译器错误,但不会将其从重载候选函数集中删除。如果用户传递了一个const char*,第二个重载将被拾取,编译器将尖叫重载被删除。

当然,您还可以为已知大小的数组提供包装器,以便它们可以安全无缝地传递文字:

template <size_t N>
void AddCell(const char (&array)[N]) {
   AddCell(array, N);
}

这允许AddCell("MyCell"),因为字面量是一个数组,最好的候选者是模板,它会依次分派到具有适当大小的(const char*,size_t) 重载。

【讨论】:

    猜你喜欢
    • 2017-01-10
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多