为什么C++ 11使" delete
d"函数参与重载决策?
为什么这有用?或者换句话说,为什么它们被隐藏而不是被完全删除?
struct A
{
A();
A(const A&);
A& operator =(const A&);
A(A&&) = delete;
A& operator =(A&&) = delete;
};
struct B
{
B();
B(const B&);
B& operator =(const B&);
};
int main()
{
A a;
a = A(); // error C2280
B b;
b = B(); // OK
}
Run Code Online (Sandbox Code Playgroud)
我的编译器是VC++ 2013 RC.
错误C2280:'A&A :: operator =(A &&)':尝试引用已删除的函数
我只是想知道为什么编译器A& operator =(const A&);
在A& operator =(A&&)
删除时不会尝试?
这种行为是由C++标准定义的吗?
我正在实现一个简单的智能指针,它基本上跟踪它处理的指针的引用数量.
我知道我可以实现移动语义,但我不认为复制智能指针非常便宜.特别是考虑到它引入了产生令人讨厌的错误的机会.
这是我的C++ 11代码(我省略了一些不必要的代码).欢迎提出一般性意见.
#ifndef SMART_PTR_H_
#define SMART_PTR_H_
#include <cstdint>
template<typename T>
class SmartPtr {
private:
struct Ptr {
T* p_;
uint64_t count_;
Ptr(T* p) : p_{p}, count_{1} {}
~Ptr() { delete p_; }
};
public:
SmartPtr(T* p) : ptr_{new Ptr{p}} {}
~SmartPtr();
SmartPtr(const SmartPtr<T>& rhs);
SmartPtr(SmartPtr<T>&& rhs) =delete;
SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
SmartPtr<T>& operator=(SmartPtr<T>&& rhs) =delete;
T& operator*() { return *ptr_->p_; }
T* operator->() { return ptr_->p_; }
uint64_t Count() const { return ptr_->count_; }
const T* …
Run Code Online (Sandbox Code Playgroud) 当按值返回本地对象时,C++编译器可以通过利用移动语义来优化不必要的副本(复制省略).
" 可以优化"意味着如果不满足适当的条件,则行为应该基于副本回退到默认的值语义返回.
因此,据我所知,按值返回可复制对象始终有效.
但编译器(clang和gcc)似乎不同意我的解释,如下面的MWE所示.
class Foo {
public:
Foo();
Foo(const Foo&);
Foo(Foo&&) = delete;
}
Foo f() { return Foo(); } // error: call to explicitly deleted constructor of 'Foo'
Foo g() { Foo a; return a; } // gcc complains, clang is fine
Foo x = g(); // error: call to explicitly deleted constructor of 'A'
Run Code Online (Sandbox Code Playgroud)
Q1:按值返回是否要求对象可移动?
Q2:如果没有,gcc和clang在我的MWE上行为不端,还是我错过了其他的东西?
如果我在类中禁止移动构造函数,我就不能再在向量中使用它:
class Foo
{
public:
Foo(int i) : i_(i) {}
Foo(Foo&&) = delete;
int i_;
};
int main()
{
std::vector<Foo> foo;
foo.push_back(Foo(1));
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样?