作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
#include <memory>
template <typename T>
class Wrapper {
public:
Wrapper() = delete;
Wrapper(const Wrapper&) = delete;
Wrapper(Wrapper&&) = delete;
~Wrapper() = default;
Wrapper(const T&) = delete;
Wrapper(T&& in) : instance{std::move(in)} {}
T instance;
};
void foo(Wrapper<std::shared_ptr<int>>) {}
int main() {
auto ptr = std::make_shared<int>(1);
foo(std::move(ptr));
}
这在 C++17 中一直有效,所以我从未想过,但为什么这段代码会尝试在 C++14 中调用 move 构造函数?它不应该在函数参数中就地构建吗?这似乎不是 c++17 的问题,但不是用 c++14 编译的。
我看到的唯一解决方法是使 foo
参数成为右值,但是我可以做些什么来使它工作而不使 foo
中的参数成为右值在 C++14 中?
我的第一个想法是,临时对象必须是构造函数才能传递给函数,但更令人惊讶的是,即使使用 -fno-elide-constructors
并取消删除似乎没有调用的 move 构造函数和复制构造函数!这是 gcc 和 clang 中的错误吗?
参见 https://wandbox.org/permlink/f6sa5Rm3NxZLy5P1对于错误看看奇怪的行为 https://wandbox.org/permlink/Kh6CG4OVbUAjvEZz
最佳答案
当您调用 foo(std::move(ptr));
时你没有给它 Wrapper<std::shared_ptr<int>>
.因此,编译器生成一个临时文件并使用它来构造 foo
的参数。现在,这个可以去掉了,我们可以直接构造一个Wrapper<std::shared_ptr<int>>
但是 move/复制构造函数仍然需要可访问,即使它从未被调用。
在 C++17 中,这不再发生。我们有guaranteed copy elision这意味着没有临时物化,而是直接构造参数。
关于c++ - 当不应调用该构造函数时,复制参数会调用已删除的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46226516/
我是一名优秀的程序员,十分优秀!