C++ const char* 到 char*

c++ const char* to char*

我有以下函数,它最初对函数参数执行一些验证。

char *doSomething(const char* first, const char* second) {

    if((first == nullptr || *first == '[=10=]') && (second == nullptr || *second == '[=10=]')) {
        return nullptr;
    } else if (first == nullptr || *first == '[=10=]') {
        return (char *) second;
    } else if (second == nullptr || *second == '[=10=]') {
        return (char *) first;
    }
    //doSomething
}

是否将函数参数 return 转换为指向内存中不同区域的新 char*?我不想让有人使用这个函数来操纵常量参数指向的值。如果一个参数为 nullptr 或为空,我希望新的 char* 被 return 编辑为与参数之一相同的值。

跟进:布尔变量会更好吗?我意识到我对每个变量执行了两次相同的检查,但我不会在此函数代码的其他任何地方使用此布尔值。

不,它不会生成任何新对象,它会简单地将 const 丢弃到您声明为不可变的内存区域。 通常会导致可怕的未定义行为,但如果它们来自非const指针,你会没事的(编辑 - 感谢@anatolyg)。

不会自动复制数据。

你也必须 return 一个 const char*。如果原始数据最初是 const,则放弃 const 并尝试通过该指针修改原始字符串的行为是未定义的:例如字符串文字。

如果需要 char* 指针,请在函数外部进行深拷贝。

更好的是,将所有这些合并并通过 const 指针传递 std::string 如果 nullptr 仍然被允许,或者通过 const 引用传递 const 如果它不是。 =18=]

您可能 return 指向第一个或第二个参数的指针,以便函数的调用者可以修改它指向的数据。您在技术上 returning 新指针(它的副本)但是由于指针的性质,调用者可以用它修改数据。

如果它对您不利,您可以 return const char *,这样调用者就不能修改它或根本不修改它。

布尔变量可以让你的代码更清晰,避免代码重复。

转换值不会复制它。如果要复制它,则必须按值传递,按指针或引用传递将允许用户操作返回值(除非它是 const)。

我不明白你为什么担心用户操纵参数,因为它们实际上是恒定的。

至于空值检查,不需要使用 bool。空检查使用起来很便宜(性能方面)。

2011 年标准说 (5.2.11/3):

The result of a pointer const_cast refers to the original object.

这很简单,可以回答您最初的问题。

它还说 (5.2.11/7):

[ Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier may produce undefined behavior (7.1.6.1). —end note ]

这意味着有时甚至可以通过新指针写入对象。不正常的示例是指向驻留在 read-only 内存中的对象的指针。这已经让人们使用指向字符串文字的指针,并且在嵌入式系统中经常发生常量。据我所知,演员表本身从来没有未定义的行为。

关于您的代码审查问题:

  • 正如其他人所说,无论如何return一个const char。
  • 调用者对结果做了什么吗?如果不是,return 表示成功或失败的布尔值,或表示几种失败模式的整数。
  • 如果调用者使用returned char指针,你return用什么表示成功?三种可能的错误情况用完了立即可用的 return 值。考虑 returning 错误代码并传递实际的 char 指针结果为 "out parameter"(指向 char 指针的指针)。

我会使用一个布尔标志来避免代码重复并减少重复:

bool secondIsEmpty = second == nullptr || *second == '[=10=]';
if( first == nullptr || *first == '[=10=]' )
    return secondIsEmpty ? nullptr : second;
else
    if( secondIsEmpty )
        return first;

对于 char *,您应该将 return 类型更改为 const char * 并从您的代码中删除 C 类型转换(无论如何您应该使用 const_cast<>)。如果您确实需要 return 来自该函数的可变字符串,这会使它变得更加复杂。您要么必须接受可变字符串作为参数,要么在某处创建缓冲区。在那种情况下,您可能应该 return 指向字符串的智能指针,由 new 分配,或者更好地使用 std::string 和 return 按值分配。

(这个回答主要是side-question如何让代码更好)

正如这里的人所说,您可能想要 return const char*:

const char *doSomething(const char* first, const char* second)
{
    ...
}

这将使您摆脱转换:

const char *doSomething(const char* first, const char* second)
{
    if (...)
    {
        return nullptr;
    }
    else if (...)
    {
        return second;
    }
    else if (...)
    {
        return first;
    }
}

你的代码思路大致是:

Find and return the non-empty string, with preference to second one; if there is none, return nullptr.

这样表示可能更容易:

const char *FindNonEmpty(const char* first, const char* second)
{
    if (second && *second)
        return second;
    else if (first && *first)
        return first;
    else
        return nullptr;
}

我在布尔上下文中使用了指针和字节。这是一个品味问题。您可能想使用显式比较;然而,有些人认为将指针用作布尔值比将其与 nullptr.

进行比较更具可读性