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