Bla*_*iwi 34 c++ functional-programming const-correctness immutability c++11
所以我有一些相当广泛的功能代码,主要数据类型是不可变的结构/类.通过制作成员变量和任何方法const,我一直在声明不变性的方式是"几乎不可变的".
struct RockSolid {
const float x;
const float y;
float MakeHarderConcrete() const { return x + y; }
}
Run Code Online (Sandbox Code Playgroud)
这实际上是C++中"我们应该这样做"的方式吗?或者,还有更好的方法?
chr*_*phb 33
你提出的方式非常好,除非在你的代码中你需要分配RockSolid变量,如下所示:
RockSolid a(0,1);
RockSolid b(0,1);
a = b;
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为编译器已删除了复制赋值运算符.
因此,另一种方法是将结构重写为具有私有数据成员的类,并且只重写公共const函数.
class RockSolid {
private:
float x;
float y;
public:
RockSolid(float _x, float _y) : x(_x), y(_y) {
}
float MakeHarderConcrete() const { return x + y; }
float getX() const { return x; }
float getY() const { return y; }
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您的RockSolid对象是(伪)不可变的,但您仍然可以进行分配.
Yak*_*ont 10
我假设你的目标是真正的不变性 - 每个对象在构造时都无法修改.您不能将一个对象分配给另一个对象.
您的设计最大的缺点是它与移动语义不兼容,移动语义可以使返回此类对象的函数更加实用.
举个例子:
struct RockSolidLayers {
const std::vector<RockSolid> layers;
};
Run Code Online (Sandbox Code Playgroud)
我们可以创建其中一个,但是如果我们有一个函数来创建它:
RockSolidLayers make_layers();
Run Code Online (Sandbox Code Playgroud)
它必须(逻辑上)将其内容复制到返回值,或使用return {}语法直接构造它.外面,你要么做:
RockSolidLayers&& layers = make_layers();
Run Code Online (Sandbox Code Playgroud)
或者(逻辑上)复制构造.无法移动构造将妨碍许多简单的方法来获得最佳代码.
现在,两个复制结构都被省略了,但更一般的情况仍然存在 - 你不能将数据从一个命名对象移动到另一个命名对象,因为C++没有"销毁和移动"操作,它们都接受一个变量范围并使用它来构造其他东西.
而且,在return local_variable;破坏之前C++将隐式移动您的对象(例如)的情况会被您的const数据成员阻止.
在围绕不可变数据设计的语言中,它会知道它可以"移动"您的数据,尽管它具有(逻辑)不变性.
解决此问题的一种方法是使用堆,并将数据存储在其中std::shared_ptr<const Foo>.现在,constness不在成员数据中,而是在变量中.您也可以只为每个返回上述类型的类型公开工厂函数shared_ptr<const Foo>,从而阻止其他构造.
这些对象可以与Bar存储std::shared_ptr<const Foo>成员一起组成.
返回a的函数std::shared_ptr<const X>可以有效地移动数据,并且局部变量可以在完成后将其状态移动到另一个函数中,而不会弄乱"真实"数据.
对于相关技术,在较少约束的C++中采用这种方法shared_ptr<const X>并将其存储在假装它们不是不可变的包装类型中是惰性的.当你进行变异操作时,shared_ptr<const X>克隆并修改,然后存储.优化"知道"它shared_ptr<const X>是"真的"a shared_ptr<X>(注意:确保工厂函数返回一个强制转换shared_ptr<X>为a shared_ptr<const X>或者这实际上不是真的),并且当use_count()为1 时抛弃const并直接修改它.这是称为"写入时复制"的技术的实现.
| 归档时间: |
|
| 查看次数: |
14491 次 |
| 最近记录: |