返回对原始参数

时间:2017-03-13 15:25:23

标签: c++ templates reference

我有这样的功能

template<typename T>
const T& get(std::string key, T defaultValue)
{
    try {
        return getFromMap<T>(key);
    }
    catch (const std::exception &e)
    {
        return defaultValue;
    }
}

从混合类型映射中检索键入的值,如果找不到键,则返回defaultValue。原始值和对象类型作为映射中的值(因此我们必须返回对值的引用)。我们只需要担心原始的defaultValues;将它与我们的对象值一起使用是不受支持的。这个函数在linux上工作正常,但是当在windows上运行时,我返回的defaultValues是垃圾。例如,

get(“missing”,true)返回false(即0)

get(“missing”,3.14)返回0

get(“missing”,“myDefault”)返回垃圾邮件地址

等等。我想问题就是将defaultValue复制到函数内的新变量中,然后返回对临时的引用。如何修复我的功能以在Windows上做正确的事情?

1 个答案:

答案 0 :(得分:2)

首先,无论操作系统如何,您的功能都会中断。原因是当异常情况发生时它具有未定义的行为:您将返回对函数本地对象(参数defaultValue)的引用。一旦函数退出,这样的引用变为悬空,并且通过悬空引用访问对象是UB。它碰巧在Linux上工作只是运气不好,它可以通过改变编译器版本,编译开关,源代码的其他部分或其他任何东西轻松破解。

我担心你遇到的问题并没有一个快速和快速的解决方案。干净。

我认为你可能最好提供两个get重载,一个用于原始类型,它将按值返回,一个用于非原始类型,它将由const T &返回(而不是支持默认值,你提到的对你来说没问题)。你可以这样做:

template<typename T, typename = std::enable_if_t<std::is_fundamental<T>::value>>
T get(const std::string &key, T defaultValue)
{
    try {
        return getFromMap<T>(key);
    }
    catch (const std::exception &e)
    {
        return defaultValue;
    }
}

template<typename T, typename = std::enable_if_t<!std::is_fundamental<T>::value>>
const T& get(const std::string &key)
{
    return getFromMap<T>(key);
}

请注意,我已将get更改为key参数const&。如果您担心性能问题,则不应仅复制key以便阅读。