在下面的代码中,如何为函数main中的对象A分配rvalue?
#include <iostream>
using namespace std;
class A
{
public:
int* x;
A(int arg) : x(new int(arg)) { cout << "ctor" << endl;}
A(const A& RVal) {
x = new int(*RVal.x);
cout << "copy ctor" << endl;
}
A(A&& RVal) {
this->x = new int(*RVal.x);
cout << "move ctor" << endl;
}
~A()
{
delete x;
}
};
int main()
{
A a(8);
A b = a;
A&& c = A(4); // it does not call move ctor? why?
cin.ignore(); …Run Code Online (Sandbox Code Playgroud) 我无法理解Foo移动构造函数~ptr在以下示例中尝试调用的原因:
#include <utility>
template <typename T, typename Policy>
class ptr {
T * m_t;
public:
ptr() noexcept : m_t(0) {}
explicit ptr(T *t) noexcept : m_t(t) {}
ptr(const ptr &other) noexcept : m_t(Policy::clone(other.m_t)) {}
ptr(ptr &&other) noexcept : m_t(other.m_t) { other.m_t = 0; }
~ptr() noexcept { Policy::delete_(m_t); }
ptr &operator=(const ptr &other) noexcept
{ ptr copy(other); swap(copy); return *this; }
ptr &operator=(ptr &&other) noexcept
{ std::swap(m_t,other.m_t); return *this; }
void swap(ptr &other) noexcept { std::swap(m_t, …Run Code Online (Sandbox Code Playgroud) 在C++中,不能依赖从return语句调用的复制构造函数,因为标准中的一个特殊子句允许编译器省略对返回语句产生的复制构造函数的调用,即使复制构造函数有副作用.因此,编写复制构造函数除了复制构造实例之外还执行其他操作是不好的方式.
在C++ 11标准中是否有类似的语句允许编译器在某些情况下消除对移动构造函数的调用 - 如果是,那么这些情况是什么?
我想确保我正确理解这一点.我在这里问它,因为我没有明确说明它的资金.
例如,我有一个三角形网格类,基本上是这样构建的:
class Mesh
{
public:
struct Face
{
unsigned int a;
unsigned int b;
unsigned int c;
};
//...
private:
std::string file;
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<glm::vec2> texcoord;
std::vector<Face> faces;
}
Run Code Online (Sandbox Code Playgroud)
由于网格中的数据可能变得非常大,我想实现适当的移动语义.对于指针类型我完全理解这一点,但要触发rvalue构造函数我需要使用move,对吧?
例如,rvalue构造函数将是:
Mesh::Mesh(Mesh&& other)
: file(std::move(other.file)),
vertices(std::move(other.vertices)),
normals(std::move(other.normals)),
texcoord(std::move(other.texcoord)),
faces(std::move(other.faces) {}
Run Code Online (Sandbox Code Playgroud)
注意:在有人指出明显的情况之前,应用程序在很多地方使用share_ptr.但我不想人为地限制班级的使用.
根据cppreference和这个答案,C++应该不自动,如果有一个用户声明析构函数生成一个移动构造函数.但是,在实践中用Clang检查这个,我看到了一个自动生成的移动构造函数.以下代码打印"is_move_constructible:1":
#include <iostream>
#include <type_traits>
struct TestClass
{
~TestClass()
{}
};
int main( int argc, char** argv )
{
std::cout << "is_move_constructible: " << std::is_move_constructible<TestClass>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我误解"没有用户声明的析构函数"或std :: is_move_constructible吗?我正在使用'-std = c ++ 14'和Apple LLVM版本7.0.2(clang-700.1.81)进行编译.
下面的代码给出了错误:
use of deleted function ‘constexpr B::B(const B&)’
Run Code Online (Sandbox Code Playgroud)
现在,我知道这是因为通过指定移动构造函数(有意)隐式删除了复制构造函数,并且复制向量会导致对(已删除)复制构造函数的调用.我想我也理解为什么使用向量的复制构造函数和赋值运算符.我显然想要使用移动构造函数和赋值运算符:移动对象,因此也移动它包含的向量.那么,如何让我的移动构造函数/赋值运算符使用向量的移动构造函数/赋值运算符?
这是代码:
#include <vector>
class B {
private:
/* something I don't want to copy */
public:
B() {};
B(B&& orig) {/* move contents */};
B& operator=(B&& rhs) {
/* move contents */
return *this;
};
};
class A {
private:
vector<B> vec;
public:
A() : vec() {};
A(A&& orig) : vec(orig.vec) {};
A& operator=(A&& rhs) {
vec = rhs.vec;
return *this;
};
};
Run Code Online (Sandbox Code Playgroud) 有一个constexpr移动构造函数是否有意义?
例如,请考虑以下事项:
#include <array>
class C
{
public:
constexpr C(std::array<int, 3> ar) : m_ar{ar} {}
constexpr C(C&& other) : m_ar{std::move(other.m_ar)} { }
private:
std::array<int, 3> m_ar;
};
int main()
{
constexpr C c1 {{{1, 2, 3}}};
constexpr C c2{std::move(c1)};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不编译,因为尽管调用std::move上c1,编译器推断它需要使用(隐含删除)拷贝构造函数,而不是移动构造函数.我不知道为什么.
但是如果我删除了constexprfrom c1,那么constexpr移动构造函数就会变得无法使用.
有没有办法让这个工作?或者这是一个constexpr移动构造函数的坏例子,但是有很好的例子吗?或者,拥有constexpr移动构造函数总是错误的吗?
我创建了以下类来理解以下行为std::sort:
class X {
public:
X(int i) : i_(i) { }
X(X&& rhs) noexcept : i_(std::move(rhs.i_)) { mc_++; }
X& operator=(X&& rhs) noexcept {
i_ = std::move(rhs.i_); ao_++; return *this;
}
void swap(X& rhs) noexcept { std::swap(i_, rhs.i_); sw_++; }
friend bool operator<(const X& lhs, const X& rhs) {
return lhs.i_ < rhs.i_;
}
static void reset() { mc_ = ao_ = sw_ = 0; }
private:
int i_;
static size_t mc_, ao_, sw_; // function-call counters …Run Code Online (Sandbox Code Playgroud) 我最近几天一直在学习(N)RVO.在我阅读c拷贝文章中的cppreference时,对于C++ 14:
...编译器是允许的,但不要求省略复制和移动 - (自C++ 11)类对象的构造,即使复制/移动(自C++ 11)构造函数和析构函数具有可观察的一面效果- .这是一个优化:即使它发生并且没有调用copy-/move-构造函数,它仍然必须存在并且可访问(好像根本没有发生优化),否则程序就会形成错误.
因此,复制或移动构造函数必须存在且可访问.但是在下面的代码中:
#include <iostream>
class myClass
{
public:
myClass() { std::cout << "Constructor" << std::endl; }
~myClass() { std::cout << "Destructor" << std::endl; }
myClass(myClass const&) { std::cout << "COPY constructor" << std::endl;}
myClass(myClass &&) = delete;
};
myClass foo()
{
return myClass{};
}
int main()
{
myClass m = foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:test.cpp: In function 'myClass foo()':
test.cpp:15:17: error: use of deleted function 'myClass::myClass(myClass&&)' …
下面的代码在Visual Studio 2013下会崩溃
我想知道为什么:在这种情况下编写移动构造函数的正确方法是什么?删除移动构造函数可以解决问题。这是 VC++ 的错误还是这段代码有错误?
移动构造函数的默认定义有什么不同,可以使此代码不会崩溃,而我自己的定义却会崩溃?
#include <memory>
#include <vector>
class A
{};
class Foo
{
public:
Foo(std::unique_ptr<A> ref) : mRef(std::move(ref)) {}
Foo(Foo&& other) : mRef(std::move(other.mRef)) {}
Foo(const Foo& other) {}
Foo& operator=(const Foo& other) { return *this; }
protected:
std::unique_ptr<A> mRef;
};
int main(int argc, char *argv[])
{
std::vector<Foo>({ Foo(std::make_unique<A>()), Foo(std::make_unique<A>()) });
// Crash : Debug Assertion Failed !
// Expression : _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
}
Run Code Online (Sandbox Code Playgroud)
可能与此有某种关系,对吧?
与 2013 年相比,initializer_list 中的双重删除
这是带有充实的复制构造函数和赋值的实际代码,但错误是完全相同的
class A
{
public:
std::unique_ptr<A> clone() { return …Run Code Online (Sandbox Code Playgroud) c++ ×10
move-constructor ×10
c++11 ×5
c++14 ×3
constexpr ×1
destructor ×1
sorting ×1
swap ×1
unique-ptr ×1
visual-c++ ×1