题
有没有办法对对象进行编码仅写作引用?例如,假设有一个静音类:
template <class T> class mutex {
protected:
T _data;
public:
mutex();
void lock(); //locks the mutex
void unlock(); //unlocks the mutex
T& data(); //returns a reference to the data, or throws an exception if lock is unowned
};
有没有办法保证不能这样做的方法:
mutex<type> foo;
type& ref;
foo.lock();
foo.data().do_stuff();
ref = foo.data();
foo.unlock();
//I have a unguarded reference to foo now
另一方面,这甚至值得吗?我知道有些人 认为 那个程序员不会故意拼凑系统,但是,为什么我们首先有私人变量,嗯?只要说这是“不确定的行为”,这真是太好了,但这似乎有点不安全。
编辑:好的,我理解二传手例程的想法,但是如何实现?
mutex<vector<int> > foo;
foo.lock();
for (int i=0; i < 10; i++) {
foo.data().push_back(i);
}
foo.unlock();使用设定的例程需要每个写的副本:
mutex<vector<int> > foo;
foo.lock();
for (int i=0; i < 10; i++) {
vector<int> copy = foo.read();
copy.push_back(i);
foo.write(copy);
}
尽管您可以在这种特定情况下进行微不足道的优化,但是如果例如,几个不同的线程都在推动元素,甚至可以删除一些元素,那么这可能会变成很多过多的内存复制(即每个关键部分一个)。
没有正确的解决方案
其他提示
是的,您可以创建一个包装器类,该类别在调用解锁时会无效并返回包装器,而不是返回引用,并且可以超载其分配运算符以分配给参考。诀窍是,您需要挂在包装器的内部数据的引用上,以便在释放锁之前调用解锁后,您将创建的任何包装器无效。
区分getters和setter的常见方法是通过对象的构成性:
template <class T> class mutex {
public:
mutex();
void lock();
void unlock();
T& data(); // cannot be invoked for const objects
const T& data() const; // can be invoked for const objects
protected:
T _data;
};
现在,如果您想拥有仅阅读访问权限,请制作sutex const:
void read_data(const mutex< std::vector<int> >& data)
{
// only const member functions can be called here
}
您可以将非CONST对象绑定到const引用:
// ...
mutex< std::vector<int> > data;
data.lock();
read_data(data);
data.unlock();
// ...
请注意 lock()
和 unlock()
面对例外,函数本质上是不安全的:
void f(const mutex< std::vector<int> >& data)
{
data.lock();
data.data().push_back(42); // might throw exception
data.unlock(); // will never be reached in push_back() throws
}
解决这个问题的通常方法是 raii (资源获取是初始化):
template <class T> class lock;
template <class T> class mutex {
public:
mutex();
protected:
T _data;
private:
friend class lock<T>;
T& data();
void lock();
void unlock();
};
template <class T> class lock {
public:
template <class T> {
lock(mutex<T>& m) m_(m) {m_.lock();}
~lock() {m_.unlock();}
T& data() {return m_.data();}
const T& data() const {return m_.data()}
private:
mutex<T>& m_;
};
请注意,我还将登录机功能移至锁类,因此无法访问解锁数据。
您可以这样使用:
void f(const mutex< std::vector<int> >& data)
{
{
lock< std::vector<int> > lock_1(data);
std::cout << lock1.data()[0]; // fine, too
lock1.data().push_back(42); // fine
}
{
const lock< std::vector<int> > lock_2(data); // note the const
std::cout << lock1.data()[0]; // fine, too
// lock1.data().push_back(42); // compiler error
}
}
您可以将数据封装为私有,并公开写入例程。在这个例程中,您可以锁定互斥X,从而使您的行为与所拍摄的相似行为。
您可以使用以下成员函数:
void set_data(const T& var);
这就是在C ++中应用仅写入的方式。
否。没有办法保证用不安全的语言(例如C ++)阅读和编写记忆的任何内容,其中所有内存都被视为一个大数组。
编辑 不确定为什么所有的下跌投票;这是正确且相关的。
在Java或C#之类的安全语言中,您当然可以保证,例如,适当的不变性类型将保持不变。这种保证永远不能在C ++中制定。
恐惧并不是恶意用户,而是偶然的无效分子。我从事C ++项目,由于无效的指针在完全不相关的代码中,不变的类型被突变了,导致错误 极其 很难追踪。这种保证(只有安全的语言才能制造)既有用,也很重要。