在C+中创建惰性对象+;,或者如何进行零成本验证 我在C语言中遇到了参数验证,现在我想知道如何在C++中实现类似的东西。我喜欢这个东西的主要一点是,在第一次验证失败之前,它不会花费任何费用,因为Begin()函数返回null,而其他函数会对此进行检查 显然,在C++中,可以实现类似的代码:验证*V=0;IsNotNull(v,…).IsInRange(v,…)并让它们中的每一个都传递到v指针上,然后返回一个代理对象,我为其复制了所有函数

在C+中创建惰性对象+;,或者如何进行零成本验证 我在C语言中遇到了参数验证,现在我想知道如何在C++中实现类似的东西。我喜欢这个东西的主要一点是,在第一次验证失败之前,它不会花费任何费用,因为Begin()函数返回null,而其他函数会对此进行检查 显然,在C++中,可以实现类似的代码:验证*V=0;IsNotNull(v,…).IsInRange(v,…)并让它们中的每一个都传递到v指针上,然后返回一个代理对象,我为其复制了所有函数,c++,validation,C++,Validation,现在我想知道是否有类似的方法可以在没有临时对象的情况下实现这一点,直到第一次验证失败。虽然我猜在堆栈上分配像std::vector这样的东西应该是免费的(这是真的吗?我怀疑一个空向量在堆上没有分配,对吧?不能对问题的其余部分说太多,但我确实想指出这一点: 虽然我猜是这样 类似于屏幕上的std::vector 堆栈应该是免费的(这是吗 真的吗?我怀疑是空的 vector不在服务器上进行分配 堆,对吗?) 不,您仍然需要在向量中分配任何其他变量(例如长度存储),我相信,如果他们在构建时为向量元素预先

现在我想知道是否有类似的方法可以在没有临时对象的情况下实现这一点,直到第一次验证失败。虽然我猜在堆栈上分配像
std::vector
这样的东西应该是免费的(这是真的吗?我怀疑一个空向量在堆上没有分配,对吧?

不能对问题的其余部分说太多,但我确实想指出这一点:

虽然我猜是这样 类似于屏幕上的std::vector 堆栈应该是免费的(这是吗 真的吗?我怀疑是空的 vector不在服务器上进行分配 堆,对吗?)

不,您仍然需要在向量中分配任何其他变量(例如长度存储),我相信,如果他们在构建时为向量元素预先分配任何空间,这取决于实现。无论哪种方式,您都在分配一些东西,虽然可能不多,但分配永远不会是“空闲”的,不管是在堆栈还是堆上进行的


话虽如此,我可以想象,做这些事情所需的时间将是如此之少,以至于只有在你快速连续做了很多次之后,这才是真正重要的。

我建议看看,它提供了基本相同的功能(向单个异常对象添加任意详细的异常信息)

<>当然,你需要编写一些实用方法,这样你就可以得到你想要的接口。但是要小心:在C++中取消一个空指针会导致未定义的行为,并且空引用甚至不可能存在。因此,你不能返回一个空指针,因为你的链接例子在C扩展方法中使用空引用。 对于零成本的事情:一个简单的堆栈分配是非常便宜的,而一个
boost::exception
对象本身不做任何堆分配,但前提是您将任何error\u info对象附加到它上。因此,它不完全是零成本的,但几乎是可以得到的最便宜的(一个vtable ptr用于异常对象,加上sizeof(intrusive\u ptr))


因此,这应该是我们试图进一步优化的最后一部分。

关于链接文章:显然,在C#中创建对象的难度很大,相比之下,函数调用是免费的

我个人会提出一个语法,比如

Validate().ISNOTNULL(src).ISNOTNULL(dst);
Validate()构造一个临时对象,它基本上只是一个std::问题列表。空列表非常便宜(没有节点,大小=0).~如果列表不是空的,则验证将抛出。如果分析显示,即使这样也太昂贵,那么您只需将std::list更改为手动滚动列表。记住,指针也是对象。您不会仅仅通过坚持原始指针的错误语法来保存对象。相反,使用漂亮的语法包装原始指针会增加开销x纯粹是编译时价格


代码> iNoStUnLy(x)< /> >是<代码> IsNotNull(x,x x) > AsXScript()如何打印失败的条件,而不必重复它。

< P>除了C++没有扩展方法(这不能够在新的验证中添加新的内容)之外,它应该太难了。
class Validation
{
    vector<string> *errors;
    void AddError(const string &error)
    {
       if (errors == NULL) errors = new vector<string>();
       errors->push_back(error);
    }

public:
    Validation() : errors(NULL) {}
    ~Validation() { delete errors; }

    const Validation &operator=(const Validation &rhs)
    {
        if (errors == NULL && rhs.errors == NULL) return *this;
        if (rhs.errors == NULL)
        {
            delete errors;
            errors = NULL;
            return *this;
        }
        vector<string> *temp = new vector<string>(*rhs.errors);
        std::swap(temp, errors);
    }

    void Check()
    { 
         if (errors)
             throw exception();
    }

    template <typename T>
    Validation &IsNotNull(T *value)
    {
        if (value == NULL) AddError("Cannot be null!");
        return *this;
    }

    template <typename T, typename S>
    Validation &IsLessThan(T valueToCheck, S maxValue)
    {
        if (valueToCheck < maxValue) AddError("Value is too big!");
        return *this;
    }

    // etc..

};


class Validate
{
public:
    static Validation Begin() { return Validation(); }
};

这就是我现在所拥有的,我只是想知道是否有更好的延迟创建对象的方案(类似于第一次使用指针时的构造)很容易获得。当你把它放在堆栈上时,成本实际上是增加堆栈指针,所以你真的不需要为此付出太多——因为没有vtable,类中只有一个指针,分配它和分配空指针一样便宜。
Validate::Begin().IsNotNull(somePointer).IsLessThan(4, 30).Check();