Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将Get()拆分为容器的Has()和Get()有什么好处吗?_C++_Search_Stl_Containers - Fatal编程技术网

C++ 将Get()拆分为容器的Has()和Get()有什么好处吗?

C++ 将Get()拆分为容器的Has()和Get()有什么好处吗?,c++,search,stl,containers,C++,Search,Stl,Containers,假设我有一个向量,和一个GetMyClass(),比如: std::vector<MyClass> mcs; // assume mcs has some elements... MyClass* GetMyClass() { auto it = std::find_if(mcs.begin(), mcs.end(), [](const MyClass& mc) { return mc.condition() == true;

假设我有一个
向量
,和一个
GetMyClass()
,比如:

std::vector<MyClass> mcs; // assume mcs has some elements...

MyClass* GetMyClass()
{
    auto it = std::find_if(mcs.begin(), mcs.end(), 
    [](const MyClass& mc)
    {
        return mc.condition() == true;
    });

    if (it == mcs.end())
        return nullptr;
    else
        return &(*it);
}
如果用户想知道是否存在
MyClass
,则调用
HasMyClass()
; 如果用户想要获得一个
MyClass
,并且非常确定必须有一个,那么他直接调用
GetMyClass()
。如果用户想要一个
MyClass
,但不确定,那么他会同时调用这两个类

为了消除代码重复并避免重复执行,我将其修改为:

std::vector<MyClass> mcs; // assume mcs has some elements...
// std::vector<MyClass>::iterator temp; // originally this
MyClass* temp = nullptr; // changed to this according to Hsi-Hung Shih's advice

bool HasMyClass()
{
    auto it = std::find_if(mcs.begin(), mcs.end(), 
    [](const MyClass& mc)
    {
        return mc.condition() == true;
    });

    if (it == mcs.end())
    {
        temp = nullptr;
        return false;
    }
    else
    {
        temp = &(*it);
        return true;
    }
}

MyClass& GetMyClass()
{
    if (temp == nullptr)
    {
        HasMyClass();
    }

    MyClass& mc = (*temp);
    temp = nullptr;
    return mc;
}
std::vector mcs;//假设mcs有一些元素。。。
//std::vector::迭代器温度;//原来这个
MyClass*temp=nullptr;//按照西鸿禧的建议改成了这样
boolhasmyclass()
{
auto it=std::find_if(mcs.begin(),mcs.end(),
[](常数MyClass和mc)
{
返回mc.condition()==true;
});
if(it==mcs.end())
{
温度=零PTR;
返回false;
}
其他的
{
温度=&(*it);
返回true;
}
}
MyClass&GetMyClass()
{
if(temp==nullptr)
{
HasMyClass();
}
MyClass&mc=(*温度);
温度=零PTR;
返回mc;
}
我的问题是:

增加一个
Has()
函数有什么好处吗?

如果是这样,这会减轻用户的负担吗?这会使代码使用的意图更加明确吗?额外的复杂性值得吗?


谢谢

我建议保留
GetMyClass
的原始实现。我将添加
HasMyClass
,作为一个方便的函数,用于那些只需要这些信息的情况。 您可以使用
GetMyClass
实现
HasMyClass
。这是一个微不足道的实现

bool HasMyClass()
{
    return (GetMyClass() != nullptr);
}
如果函数使用

if ( HasMyClass() )
{
    MyClass* c = GetMyClass();
}
将进行两次搜索。这是对函数的错误使用,但您无法阻止它们

更好地使用HasMyClass的方法是:

if ( HasMyClass() )
{
  // Follow path 1 (does not involve call to GetMyClass)
}
else
{
  // Follow path 2 (does not involve call to GetMyClass either)
}
而且很确定一定有一个

已经给出了答案:如果你不能确定,你不能不检查就处理返回值

但是这种编程看起来像是一个旧的posix接口,必须检查每个retval。从C++中,你可以从STL中获得更多的功能,而不用编写这样的代码。我建议您查看一下

或者干脆全部:

我相信你可以用stl功能做很多事情。编写自己的搜索函数、访问它们、检查检索以及使用值/迭代器执行某些操作通常不能通过手工编写的代码来完成


第二次尝试可能是抛出异常,如
throw NotFound_t()

通常的实现是更改接口以将指针作为参数传递,并返回是否找到对象:

bool TryGetMyClass(MyClass* ptr)
{
    auto it = std::find_if(mcs.begin(), mcs.end(), 
    [](const MyClass& mc)
    {
        return mc.condition() == true;
    });

    if (it == mcs.end())
    { 
       ptr = nullptr;
       return false;
    }
    else
    {
       ptr = &(*it);
       return true;
    }
}
用法示例:

if(TryGetMyClass(ptr))
  ... // Ok, ptr not null
else
  ... // Handle null pointer

检查返回值是否存在潜在故障是常见的API设计,因此程序员应该熟悉它,并且可以轻松地使用它。如果他们忘记检查它,他们将知道何时取消引用它

当找不到异常时,可以抛出异常,但在容器中找不到异常通常不是异常,最好不要抛出异常

顺便说一下,您的代码也很危险,因为迭代器“temp”在您之前的查找之后可能无效。它可能是从向量中删除项的结果。副作用不明的功能非常差

总之,让人们熟悉您的API。不要为了使代码看起来可爱而使代码复杂化,比如允许人们不检查返回值是否存在潜在故障

编辑

如果您的数据可以是nullptr,那么您可以定义一个要返回的数据类,在该类中它可以指示故障状态。如果您很懒,可以使用std::pair来完成这项工作

struct Data {
    bool is_failed;
    MyClass* data;
};

老实说,这些函数表明,包装STL方法并没有实现任何功能。那些已经有一个成熟的模式来沟通“没有发现”,C++程序员已经熟悉了。你的方法连你自己都弄糊涂了


相反,您应该做的是在
std::find
中提供合适的谓词

返回MyClass.condition()==true??你的意思是
返回mc.condition()==true如果用户不确定并同时调用这两个,则搜索将执行两次,而之前只执行一次。此外,您首先假定用户不确定,但无法检查
nullptr
的返回值。为什么您相信同一个用户不会不调用Has()
?您在if(temp==mcs.end()
return&(*it);
局部变量的返回地址
UB
@billz:False.
&(*it)中遗漏了一些括号
是向量中某个元素的地址。您考虑的是
&it
。但是通常
HasMyClass()
会导致
GetMyClass()
,这就是为什么我试图借助
temp
迭代器避免这两次搜索,以便可以调用
if(!HasMyClass())return;MyClass*c=GetMyClass();c->剂量测定法();
无需进行两次搜索。@MarsonMao,你可以这样做。但是,将迭代器作为全局变量存储在函数外部不是一个好的设计决策。是的,我知道,实际上向量和迭代器以及这些方法将被包装在一个类中;向量和迭代器将是私有成员。我将它们作为全局成员,只是为了含蓄性。@MarsonMao,那就没那么糟糕了。是的,检查retval非常烦人。但是我不太明白为什么我应该对每个
使用
。在这种情况下,你能给我一些提示吗?你是对的,我应该对
临时
使用
MyClass*
,而不是迭代器。但我试图实现的是为了用户,我认为在很多情况下检查返回值是烦人和多余的
struct Data {
    bool is_failed;
    MyClass* data;
};