我为不可复制的类创建了这个基类:
class manager
: public non_copyable
{
public:
manager()
{
}
std::string s;
};
然后我创建了这个派生类:
manager get()
{
return manager();
}
我能够创建该类的实例并将其返回:
def Gaussian(sigma, x, mu):
p = 1/(sigma*np.sqrt(2*np.pi))*np.exp(-(x-mu)**2/(2*sigma**2))
return p
N = 10
i = 0
x[0] = 0.5
results = []
for i in range (0,N):
y = x[i] + np.random.normal(0,0.01)
H = Gaussian(1,y,1)/Gaussian(1,x[i],1)
alpha = np.random.uniform(1,1)
if H >= alpha:
x[i+1]=y
results.append(y)
print(results)
我认为这是不可能的,因为删除了复制构造函数并删除了隐式生成的移动构造函数,因为存在用户定义(已删除)的复制构造函数。
此代码使用MinGW-64 7.2进行编译,但不使用MSVC 2017进行编译,并收到此消息:
function" manager :: operator =(const manager&)throw()" (隐式声明)无法引用 - 它是一个已删除的函数
这是编译器的问题,C ++设计允许还是我做错了什么?
答案 0 :(得分:6)
在C ++ 17中,此操作既不需要移动也不需要复制; the entire thing is elided
因此,Visual Studio在实现此语言标准时要错误或不完整。†
一般来说,尽量不要改变C ++自己的语义。防止昂贵的东西很好,但防止免费的东西是IMO的一个步骤。
†根据您的确切版本,this blog post可能相关 - 它表明他们试图使此功能正常工作,但它太破碎了,所以他们推出了它回到现在;我不知道是否有更新版本实现它。
答案 1 :(得分:4)
从C ++ 17开始,我们保证copy elision。这意味着从函数返回值不需要复制或移动。
不幸的是,Visual Studio doesn't yet support this:
P0135R1保证复制省略号
答案 2 :(得分:3)
在c++17中,prvalue表达式不是逻辑对象。在c++14中,它们在逻辑上是对象(或者更确切地说是对象)。
现在,prvalue表达式是关于如何制作对象的指令。在某些情况下,这些指令适用于创建临时或非临时对象。
这通常被称为“保证省略”。但实际上它在许多情况下(不是全部)都消除了对elision的任何需求。
manager get() {
return manager();
}
在c++14 manager()
中是一个创建对象的prvalue表达式。返回值是另一个prvalue。这些具有其身份和生命周期合并的两个对象可以<{1}}复制或移动到manager()
的返回值 。
在c++17 get
中是prvalue,manager()
的返回值也是如此。您没有“复制”或“移动”有关如何创建对象的指令,也没有对象。返回只是告诉返回值“这里是你需要的指令”。
get()
这里我们从prvalue构建manager foo = get();
- 来自如何制作foo
的说明。没有创建临时对象;相反,我们只是按照manager
的prvalue返回指示构造对象。
在c++14中我们会有一个临时管理器对象,其生命周期可以通过命名对象get()
来消除。
这种省略和直接使用prvalues的效果在运行时非常相似,但其中一个涉及我们后来消除的逻辑移动或复制构造函数调用,另一个从未有过第二个对象开始。
为什么MSVC2017的行为不同,他们对c++11的实施仍然不完整(每年都以较小的方式,但我仍然被烧伤),更不用说c++17。