我有以下函数,它最初对函数参数执行一些验证。
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
或为空。
跟进:布尔变量会更好吗?我意识到我正在对每个变量执行两次相同的检查,但我不会在此函数的代码中的任何其他位置使用此布尔值。
答案 0 :(得分:5)
不,它不会使任何新对象简单地将const
强制转换为您声明为不可变的内存区域。哪个通常会导致可怕的未定义行为,但如果它们来自非const
指针,那么你就可以了(编辑 - 感谢@anatolyg)。
答案 1 :(得分:2)
不会自动复制数据。
您也必须返回const char*
。如果原始数据最初为const
,则抛弃const
并尝试通过该指针修改原始字符串的行为是未定义的:例如字符串文字。
如果需要char*
指针,请在函数外部进行深层复制。
更好的是,如果仍然允许std::string
,则通过const
指针移除nullptr
,如果不是const
引用则传递wdio
。
答案 2 :(得分:2)
2011年标准(5.2.11 / 3):
指针const_cast的结果是指原始对象。
这非常简单,可以回答你原来的问题。
它还说(5.2.11 / 7):
[注意:根据对象的类型,通过写操作 由a产生的数据成员的指针,左值或指针 抛弃const限定符的const_cast可能会产生undefined 行为(7.1.6.1)。 - 后注]
这意味着有时甚至可以通过新指针写入对象。不合适的示例是指向驻留在只读存储器中的对象的指针。这会使人们使用指向字符串文字的指针,并经常在嵌入式系统中使用常量。就我所见,演员本身并不是未定义的行为。
关于您的代码审核问题:
答案 3 :(得分:0)
您可能返回指向第一个或第二个参数的指针,因此函数的调用者可以修改它指向的数据。您在技术上返回新指针(它的副本),但由于指针性质,调用者可以使用它修改数据。
如果它不好你可以返回const char *,所以调用者不能修改它或根本不返回它。
布尔变量可以使您的代码更清晰,避免代码重复。
答案 4 :(得分:0)
转换值不会复制它。如果你想复制它,你必须通过值传递,通过指针或引用传递将允许用户操纵返回的值(除非它const
)。
我不明白为什么你担心用户操纵参数,因为它们实际上是不变的。
至于空检查,使用bool
是不必要的。空检查使用起来很便宜(性能明智)。
答案 5 :(得分:0)
我会使用一个布尔标志来避免代码重复并使其不易发生:
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
并按值返回。
答案 6 :(得分:0)
(这个答案主要是关于如何使代码更好的一个侧面问题)
正如此处的人所说,您可能想要返回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
一个;如果没有,请返回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
进行比较更具可读性。