Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.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++ 非常量对象的常量向量_C++_Vector_Constants_Const Correctness - Fatal编程技术网

C++ 非常量对象的常量向量

C++ 非常量对象的常量向量,c++,vector,constants,const-correctness,C++,Vector,Constants,Const Correctness,在接口中定义函数时: virtual void ModifyPreComputedCoeffs ( std::vector < IndexCoeffPair_t > & model_ ) = 0; virtualvoid modifyprecomputeredcoeffs(std::vector&model)=0; 我们想指定向量模型不应该被改变,因为push\u back等操作不应该在向量上执行,但是模型中的indexcoefffpair\u t struct对象可以被

在接口中定义函数时:

virtual void ModifyPreComputedCoeffs ( std::vector < IndexCoeffPair_t > & model_ ) = 0;
virtualvoid modifyprecomputeredcoeffs(std::vector&model)=0;
我们想指定向量模型不应该被改变,因为push\u back等操作不应该在向量上执行,但是模型中的indexcoefffpair\u t struct对象可以被改变。 我们应该如何具体说明这一点

virtual void ModifyPreComputedCoeffs ( const std::vector < IndexCoeffPair_t > & model_ ) = 0;
virtualvoid modifyprecomputeredcoeffs(const std::vector&model)=0;

我认为不起作用。

与其将向量传递到函数中,不如像标准库那样传递一对迭代器

virtual void ModifyPreComputedCoeffs ( std::vector < IndexCoeffPair_t >::iterator & model_begin, std::vector < IndexCoeffPair_t >::iterator & model_end )
virtualvoid modifyprecomputeredcoeffs(std::vector:迭代器和模型开始,std::vector::迭代器和模型结束)

< C++的正确性概念是被高估的。你刚刚发现的是它有一个很大的局限性:它不能按组成进行缩放。 为了能够创建非常量对象的常量向量,您需要实现自己的向量类型。请注意,例如,即使是标准库也必须为常量迭代器引入新类型

我的建议是在你被迫的地方使用常量正确性,而不是在你能做到的任何地方。从理论上讲,const正确性应该对程序员有所帮助,但由于语法的原因,成本非常高,而且非常原始(只有一个位,不能按组合进行扩展,甚至需要代码复制)

根据我的经验,这个所谓的大帮助其实并没有那么大。。。它捕获的大多数错误都与常量正确性机制本身有关,而与程序逻辑无关


有没有想过为什么大多数语言(包括在C++之后设计的语言)没有实现这个想法?

如果您能够修改
indexcoefffpair\u t
,您可以添加一些常量成员函数,并使用它们通过使用mutable关键字使成员可变来更改其某些成员。这是一种黑客行为,因为现在您可以更改任何
常量indexcoefffpair\t
的内容

例如:

class IndexCoeffPair_t {
public:
    void changeX(int newVal) const {
        x = newVal;
    }

private:
    mutable int x;
};

这可能是在C++14中实现的


实际上,如果大小在编译时是固定的,您可以使用。但它可能更适用于嵌入式编程、缓冲区、矩阵等,因为通常在运行时之前您不知道所需的大小,或者您希望它是可配置的。

您可以尝试创建
const std::vector
。然后,您不能更改向量,但可以更改向量内的对象。 但要准确,因为您将修改原始对象而不是副本


使用智能指针或原始指针取决于您的用例:您有自己的向量或只是观察者的向量。

以下是MahlerFive答案的通用版本:

template<typename T>
class Mutable {
    mutable T m_val;
public:
    constexpr Mutable(T const& val) : m_val(val) { }
    constexpr Mutable(T&& val) : m_val(val) { }

    // note: all member functions are `const`
    constexpr Mutable const& operator=(T const& val) const {
        m_val = val;
        return *this;
    }
    constexpr Mutable const& operator=(T&& val) const {
        m_val = val;
        return *this;
    }

    constexpr operator T&() const {
        return m_val;
    }
};
模板
类可变{
可变T m_val;
公众:
constexpr可变(T const&val):m_val(val){}
constexpr可变(T&&val):mu val(val){}
//注:所有成员函数均为“常量”`
constexpr可变常量和运算符=(T常量和val)常量{
m_val=val;
归还*这个;
}
constexpr可变常量和运算符=(T&&val)常量{
m_val=val;
归还*这个;
}
constexpr运算符T&()const{
返回m_val;
}
};

然后,您可以在代码中使用
std::vector const
,这将主要按照预期的方式运行。

不起作用,您认为呢?看起来它确实应该工作,你试过修改它吗?@yan:不,它不应该工作,因为
vector::operator[]const
和所有其他
const
元素访问器返回
vector::const\u reference
@yan,常量向量只返回对内容的常量引用-你不能修改它们。@yan:我是说我试过了,这对我不起作用。不完全确定我是否做错了什么。现在就明白原因了。谢谢Mark&User349433你回避了这个问题。如果他/她需要传递一个这样的向量呢?@6502,这似乎超出了原始问题的范围,你不觉得吗?不太可能。他问如何指定这样一个向量,你建议他不应该传递一个向量,而应该传递两个迭代器。虽然在这种特定情况下,这可能只会带来一点小麻烦(两个参数而不是一个),但它不会缩放,也不会回答最初的问题(如何指定该向量)。不幸的是C++中的答案是“你不能,你必须定义你自己的向量类来做这件事”。@ 6502:我不明白你在说什么,不是缩放。您可以编写相对简单的平坦迭代器,它将非常容易地处理深度。我也不太喜欢const,但我认为你在这方面没有优势。@6502:大多数时候人们不想听到“那是不可能的”,他们想知道如何实现它。像这样的事情完全违背了
const
关键字的目的。如果某个东西是常量,那么为什么还要麻烦呢是的,一般来说,你应该避免使用
mutable
,这就是为什么我说这是一种黑客行为。然而,由于OP希望向量是常量,而不是包含的对象,这将解决这个特定的问题。依我看,这是更大的问题。一件事是担心将来可能会误用单个函数(?)(您意外调用
push_back
?),另一件事是说所有用户都可以修改const对象的可观察状态。折衷办法是创建一个
可变的
,就像我在下面的回答中所做的那样,而不是使<代码> t>代码>本身变为错误。无论是什么观点,无论是在C++中,还是正确的,都是一个重要的特性,如果避免,会导致生产代码中的重大头痛和时间和金钱损失。虽然我喜欢这种情绪(也不一定不同意),但它更多的是对原始问题的评论,而不是答案。6502-您针对常量迭代器an进行了类似的论证