Scott Meyers 的第 30 项 "more effective C++"绘制出“代理对象”编程设计模式。
问题是如果您有:
X x;
x[3]=42;
cout<<x[3]
...您需要 X 的运算符[]重载才能区分 L 值和 R 值的使用。
(也许您需要运行不同的代码,例如,在第一种情况下可能会涉及大量复制,但在第二种情况下也许我们可以只传回引用)。
代理模式是X包含一个Proxy类,X的operator[]重载返回一个Proxy类型的对象。
这样代码就变成了:
X x;
{some Proxy object}=42;
cout<<{some Proxy object}
现在我们只需为代理对象提供“operator=”的重写,它处理第一种情况,以及“转换为 std::string 或 char*”的重写,它处理第二种情况。
C++ 尝试找到合适的类型转换将触发相关的覆盖。
但是,本书是在 C++11 之前编写的,C++11 的主要功能之一是新的 &&(R 值引用)运算符。
现在是否有一种更简单的方法来编码单独的 R 值和 L 值分配?
这种代理对象设计模式现在已经过时了吗?
最佳答案
不,我不相信这里还有替代机制。
虽然引用限定方法可以在某些情况下提供不同的行为,但重载是根据调用它们的对象的状态来解析的。它们没有解决它们返回的对象的使用问题。
如下live example ,我围绕 std::vector
创建一个包装器,尝试在分配到索引时自动增长向量,并在仅从索引读取时允许未定义的行为。
但事实并非如此:
template <typename T>
struct AutoVector
{
std::vector<T> m_vec;
AutoVector() { m_vec.resize(1); }
T& operator[](const size_t index) &
{
std::cout << "Inside operator[" << index << "]&\n";
if (m_vec.size() < index)
m_vec.resize(index);
return m_vec[index];
}
T operator[](const size_t index) &&
{
std::cout << "Inside operator[" << index << "]&&\n";
return m_vec[index];
}
};
如果通过以下方式调用,两者都会调用左值限定的operator[] &
:
AutoVector<int> avec;
avec[4] = 6;
std::cout << avec[4] << "\n";
--> Inside operator[4]&
--> Inside operator[4]&
--> 6
如果在临时对象上调用它,它可以调用右值限定的operator[] &&
:
std::cout << AutoVector<int>()[0] << "\n";
--> Inside operator[0]&&
--> 0
这没有达到预期的行为。对 operator[]
返回的代理对象应用相同类型的测试通常会导致它在所有情况下都调用右值限定的方法,除非代理被捕获并命名。它仍然无法反射(reflect)代理的使用方式。
关于design-patterns - C++1 1's && (R-value reference) operator obsolete the ' 代理对象的设计模式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26529354/