有没有办法对对象进行编码仅写作引用?例如,假设有一个静音类:

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 ++项目,由于无效的指针在完全不相关的代码中,不变的类型被突变了,导致错误 极其 很难追踪。这种保证(只有安全的语言才能制造)既有用,也很重要。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top