C++ c++;常量字符*到字符*

C++ c++;常量字符*到字符*,c++,pointers,casting,constants,nullptr,C++,Pointers,Casting,Constants,Nullptr,我有以下函数,它最初对函数参数执行一些验证 char *doSomething(const char* first, const char* second) { if((first == nullptr || *first == '\0') && (second == nullptr || *second == '\0')) { return nullptr; } else if (first == nullptr || *first == '\

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

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

    if((first == nullptr || *first == '\0') && (second == nullptr || *second == '\0')) {
        return nullptr;
    } else if (first == nullptr || *first == '\0') {
        return (char *) second;
    } else if (second == nullptr || *second == '\0') {
        return (char *) first;
    }
    //doSomething
}
转换函数参数是否返回指向内存中不同区域的新
char*
?我不想允许使用此函数的人操纵常量参数所指向的值。我希望返回一个新的
char*
,如果其中一个参数为
nullptr
或为空,则返回的值与其中一个参数的值相同


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

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

不会自动复制数据

您还必须返回一个
常量字符*
。如果原始数据最初是
常量
:例如字符串文字,则丢弃
常量
并尝试通过该指针修改原始字符串的行为是未定义的

如果需要
char*
指针,请在函数外部进行深度复制


更好的是,将所有这些都放入bin并通过
std::string
传递,如果
nullptr
仍然允许,则通过
const
指针传递,如果不允许,则通过
const
引用传递。

您可能返回指向第一个或第二个参数的指针,以便函数的调用方可以修改它所指向的数据。从技术上讲,您返回的是新指针(它的副本),但由于指针的性质,调用方可以使用它修改数据

若它对您不利,您可以返回constchar*,这样调用者就不能修改它或根本不返回它


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

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

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

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

2011标准说(5.2.11/3):

指针常量转换的结果引用原始对象

这很简单,回答了你最初的问题

它还说(5.2.11/7):

[注意:根据对象的类型,通过 由 丢弃常量限定符的常量强制转换可能会产生未定义的 行为(7.1.6.1)。-结束注释]

这意味着有时甚至可以通过新指针写入对象。不正常的例子是指向驻留在只读内存中的对象的指针。这让使用字符串文本指针的人感到痛苦,并且在嵌入式系统中经常使用常量。就我所见,演员本身从来都不是未定义的行为

关于您的代码审查问题:

  • 正如其他人所说,无论如何都要返回一个const char
  • 调用者对结果做了什么吗?如果不是,则返回一个表示成功或失败的bool,或者返回几个故障模式的int
  • 如果调用方使用返回的char指针,那么返回什么来表示成功?这三种可能的错误情况使用了立即可用的返回值。考虑返回一个错误代码,并将实际的char指针传递到一个“out参数”(指向char指针的指针)。

我会使用一个布尔标志来避免代码重复,并降低代码重复的可能性:

bool secondIsEmpty = second == nullptr || *second == '\0';
if( first == nullptr || *first == '\0' )
    return secondIsEmpty ? nullptr : second;
else
    if( secondIsEmpty )
        return first;
对于
char*
,您应该将返回类型更改为
const char*
,并从代码中删除C cast(无论如何都应该使用const_cast)。如果您确实需要从该函数返回可变字符串,这会使它变得更复杂。您要么接受可变字符串作为参数,要么在某处创建缓冲区。在这种情况下,您可能应该返回由
new
分配的字符串的智能指针,或者更好地使用
std::string
并按值返回它。

(这个答案主要是关于如何改进代码的一个附带问题)

正如这里的人所指出的,您可能希望返回
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;
    }
}
您的代码大致如下:

查找并返回非空字符串,首选
second
one;如果没有,则返回
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

进行比较更具可读性,然后,我称之为
doSomething(“hello”,“world!”)[0]='X'和轰!西格塞格夫。(答案是否定的,您必须
strncpy()
这些字符串。如果您不想让使用此函数的人操纵常量参数指向的值,该值通过
const char*
返回或通过值返回。此函数执行隐式
const_cast
转换。您的意思是要返回字符串的可变副本吗?否则,为什么你不只是返回一个
const char*
?我认为不仅通常而且总是
const\u cast
都很好。它不会导致UB。在某些情况下,通过结果指针写入对象(而不是读取!)可能会导致UB。其中一个(唯一的一个?)是对象是I