我想在编译器通常自动生成默认构造函数,复制构造函数和赋值运算符的条件下刷新内存.
我记得有一些规则,但我不记得了,也无法在网上找到有信誉的资源.有人可以帮忙吗?
c++ copy-constructor default-constructor move-constructor move-assignment-operator
按设计,std::mutex不可移动也不可复制.这意味着A拥有互斥锁的类不会接收default-move-constructor.
如何A以线程安全的方式使这种类型移动?
请考虑以下示例:
#include <iostream>
#include <string>
#include <utility>
template <typename Base> struct Foo : public Base {
using Base::Base;
};
struct Bar {
Bar(const Bar&) { }
Bar(Bar&&) = delete;
};
int main() {
std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}
Run Code Online (Sandbox Code Playgroud)
尽管基类是不可移动构造的,为什么编译器会生成移动构造函数?
这是标准还是编译器错误?是否有可能"完美地传播"将构造从基础移动到派生类?
从我正在采用的C++课程中移动构造函数实现看起来有点像这样:
/// Move constructor
Motorcycle::Motorcycle(Motorcycle&& ori)
: m_wheels(std::move(ori.m_wheels)),
m_speed(ori.m_speed),
m_direction(ori.m_direction)
{
ori.m_wheels = array<Wheel, 2>();
ori.m_speed = 0.0;
ori.m_direction = 0.0;
}
Run Code Online (Sandbox Code Playgroud)
(m_wheels是类型的成员std::array<Wheel, 2>,并且轮只包含一个double m_speed和一个bool m_rotating在所述摩托车类,m_speed并且m_direction也double峰)
我不太明白为什么ori需要清除价值.
如果a Motorcycle有任何指针成员我们想"偷",那么肯定,我们必须设置ori.m_thingy = nullptr为不要,例如,delete m_thingy两次.但是当字段包含对象本身时,这是否重要?
我向朋友询问了这个问题,他们指着我这个页面说:
移动构造函数通常会"窃取"参数所持有的资源(例如,指向动态分配的对象,文件描述符,TCP套接字,I/O流,运行线程等),而不是复制它们,并保留参数一些有效但不确定的国家.例如,从a
std::string或a 移动std::vector可能会导致参数保持为空.但是,不应依赖此行为.
谁定义了不确定状态的含义?我看不出如何设定的速度0.0是任何更多的不确定比离开它是.就像报价中的最后一句所说 - 代码不应该依赖于移动摩托车的状态,所以为什么还要打扰它?
在一些地方,我已经看到了复制和移动构造函数的推荐签名,如下所示:
struct T
{
T();
T(const T& other);
T(T&& other);
};
Run Code Online (Sandbox Code Playgroud)
复制构造函数采用const引用,移动构造函数采用非const rvalue引用.
据我所知,这使我无法在从函数返回const对象时利用移动语义,例如下面的情况:
T generate_t()
{
const T t;
return t;
}
Run Code Online (Sandbox Code Playgroud)
使用VC11 Beta进行测试,T调用复制构造函数,而不是移动构造函数.即使使用return std::move(t);复制构造函数仍然被调用.
我可以看到这是有道理的,因为tconst是不应该绑定的T&&.使用const T&&在移动构造函数签名工作正常,并且是有道理的,但你必须是因为这个问题other是常量,你不能将它的会员空出来,如果他们需要被清零了-当所有的成员都标量它只会工作或者使用正确的签名移动构造函数.
它看起来是确保在一般情况下调用移动构造t函数以便首先创建非const 的唯一方法,但我不喜欢这样做 - 构造事物是好的形式,我不希望客户T要知道他们必须反对这种形式才能提高性能.
所以,我想我的问题是双重的; 首先,移动构造函数应该采用const还是非const rvalue引用?第二:我在这种推理中是对的吗?我应该停止返回const的东西?
我有一个大班,拿着很多STL容器.
编译器会自动创建一个移动构造函数来将这些容器移动到目标,还是我必须自己创建?
根据this question的答案,可以noexcept在某些条件下定义默认移动构造函数。例如,下面的类生成一个noexcept移动构造函数:
class C {};
Run Code Online (Sandbox Code Playgroud)
根据对这个问题的回答,使用说明= default符定义的移动构造函数将生成与隐式定义的移动构造函数相同的构造函数。所以,如果我正确理解它,下面的类应该生成一个noexcept移动构造函数:
class D {
D(D&&) = default;
};
Run Code Online (Sandbox Code Playgroud)
要检查,我使用的std::is_nothrow_move_constructible功能,看是否C和D有一个noexcept移动构造函数:
#include <type_traits>
int main() {
static_assert(std::is_nothrow_move_constructible<C>::value, "C should be noexcept MoveConstructible");
static_assert(std::is_nothrow_move_constructible<D>::value, "D should be noexcept MoveConstructible");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译时,我收到此错误:
$ g++ toy.cpp -o toy
toy.cpp: In function ‘int main()’:
toy.cpp:16:5: error: static assertion failed: D should be noexcept MoveConstructible
static_assert(std::is_nothrow_move_constructible<D>::value, "D should be …Run Code Online (Sandbox Code Playgroud) 我喜欢const成员变量的想法,特别是当我将C函数包装到类中时.构造函数获取在整个对象生命周期内保持有效的资源句柄(例如文件描述符),析构函数最终将其关闭.(那是RAII背后的想法,对吧?)
但是使用C++ 0x移动构造函数我遇到了问题.由于析构函数也在"卸载"对象上调用,我需要防止资源句柄的清理.由于成员变量是const,我无法分配值-1或INVALID_HANDLE(或等效值)来向析构函数指示它不应该执行任何操作.
有没有办法在对象的状态被移动到另一个对象时不调用析构函数?
例:
class File
{
public:
// Kind of "named constructor" or "static factory method"
static File open(const char *fileName, const char *modes)
{
FILE *handle = fopen(fileName, modes);
return File(handle);
}
private:
FILE * const handle;
public:
File(FILE *handle) : handle(handle)
{
}
~File()
{
fclose(handle);
}
File(File &&other) : handle(other.handle)
{
// The compiler should not call the destructor of the "other"
// object.
}
File(const File &other) = delete;
File &operator =(const File &other) …Run Code Online (Sandbox Code Playgroud) 我一直在探索C++ 中Move Constructors的可能性,我想知道在下面的例子中有哪些方法可以利用这个功能.考虑以下代码:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
// ??? How can we take advantage of move constructors here?
}
// ... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() …Run Code Online (Sandbox Code Playgroud) 如果我有一个带有n个参数的构造函数,那么任何参数都可以是rvalue和lvalue.是否可以通过为rvalues移动语义来支持这一点,而无需为每个可能的rvalue/lvalue组合编写2 ^ n个构造函数?