我一直在测试一些C++ 11的一些功能.我遇到了r值引用并移动构造函数.
我实现了我的第一个移动构造函数,这里是:
#include <iostream>
#include <vector>
using namespace std;
class TestClass{
public:
TestClass(int s):
size(s), arr(new int[s]){
}
~TestClass(){
if (arr)
delete arr;
}
// copy constructor
TestClass(const TestClass& other):
size(other.size), arr(new int[other.size]){
std::copy(other.arr, other.arr + other.size, arr);
}
// move constructor
TestClass(TestClass&& other){
arr=other.arr;
size=other.size;
other.arr=nullptr;
other.size=0;
}
private:
int size;
int * arr;
};
int main(){
vector<TestClass> vec;
clock_t start=clock();
for(int i=0;i<500000;i++){
vec.push_back(TestClass(1000));
}
clock_t stop=clock();
cout<<stop-start<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常.无论如何把一个std :: cout放在复制构造函数中我注意到它被调用了!并且很多次..(移动构造函数500000次,复制构造函数524287次).
让我感到惊讶的是,如果我从代码中注释掉复制构造函数,整个程序会更快,而这次移动构造函数被称为1024287次.
任何线索?
explicit对于可以使用一个参数调用的所有 大多数构造函数,建议使用该关键字,但复制构造函数除外.
对于复制构造函数,它有一个用途(禁止通过函数调用,返回等隐式复制),但它不是通常想要的.
移动构造函数怎么样?是否有任何合理的用例使它们明确?这里的好习惯是什么?
我很困惑何时调用移动构造函数与复制构造函数.我已经阅读了以下资料:
所有这些来源要么过于复杂(我只想要一个简单的例子),要么只展示如何编写移动构造函数,而不是如何调用它.我写了一个简单的问题更具体:
const class noConstruct{}NoConstruct;
class a
{
private:
int *Array;
public:
a();
a(noConstruct);
a(const a&);
a& operator=(const a&);
a(a&&);
a& operator=(a&&);
~a();
};
a::a()
{
Array=new int[5]{1,2,3,4,5};
}
a::a(noConstruct Parameter)
{
Array=nullptr;
}
a::a(const a& Old): Array(Old.Array)
{
}
a& a::operator=(const a&Old)
{
delete[] Array;
Array=new int[5];
for (int i=0;i!=5;i++)
{
Array[i]=Old.Array[i];
}
return *this;
}
a::a(a&&Old)
{
Array=Old.Array;
Old.Array=nullptr;
}
a& a::operator=(a&&Old)
{
Array=Old.Array;
Old.Array=nullptr;
return *this;
}
a::~a()
{
delete[] Array;
} …Run Code Online (Sandbox Code Playgroud) 看看这段代码:
class Foo
{
public:
string name;
Foo(string n) : name{n}
{
cout << "CTOR (" << name << ")" << endl;
}
Foo(Foo&& moved)
{
cout << "MOVE CTOR (moving " << moved.name << " into -> " << name << ")" << endl;
name = moved.name + " ###";
}
~Foo()
{
cout << "DTOR of " << name << endl;
}
};
Foo f()
{
return Foo("Hello");
}
int main()
{
Foo myObject = f();
cout << …Run Code Online (Sandbox Code Playgroud) 我似乎无法使用g ++来编译使用移动构造函数的c ++ 11代码.我一直收到这个错误:
collin@Serenity:~/Projects/arraylib$ g++ ./t2.cpp
./t2.cpp:10:27: error: expected ‘,’ or ‘...’ before ‘&&’ token
./t2.cpp:10:38: error: invalid constructor; you probably meant ‘Blarg (const Blarg&)’
Run Code Online (Sandbox Code Playgroud)
我正在编写的程序与此完全不同,但我将其修改为看起来应该绝对可行的部分,但仍会触发错误:
#include <iostream>
using namespace std;
class Blarg {
public:
Blarg () {};
Blarg (const Blarg& original) {}; /* Copy constructor */
Blarg (Blarg&& original) {}; /* Move constructor */
};
int main(int argc, char *argv[])
{
Blarg b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
谁能告诉我我做错了什么?相反,如何解决它?
这是我的gcc版本:
gcc (Ubuntu/Linaro 4.6.2-14ubuntu2) 4.6.2
Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A(int) { cout << "int" << endl; }
A(A&&) { cout << "move" << endl; }
A(const A&) { cout << "copy" << endl; }
};
int main()
{
vector<A> v
{
A(10), A(20), A(30)
};
_getch();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
int
int
int
copy
copy
copy
Run Code Online (Sandbox Code Playgroud)
A(10),A(20)并且A(30)是临时对象,对不对?
那么为什么复制构造函数被调用?不应该调用移动构造函数吗?
路过move(A(10)),move(A(20)),move(A(30))相反,输出为:
int
move
int
move
int
move
copy …Run Code Online (Sandbox Code Playgroud) 假设你想利用移动语义,但你的一个可移动类需要成为一部分std::pair.目的是创建一个函数,该函数返回一个std::pair可被视为右值并转发的函数.
但我无法看到如何做到这一点,除非对其std::pair自身进行内部更改,以使其了解移动语义.
请考虑以下代码:
struct Foo
{
Foo() { }
Foo(Foo&& f) { }
private:
Foo(const Foo& f) { } // do not allow copying
};
int main()
{
Foo f;
std::pair<Foo, int> res = std::make_pair(f, 10); // fails due to private copy constructor
}
Run Code Online (Sandbox Code Playgroud)
问题是std::make_pair,除了std::pair构造函数本身之外,还需要两个对象并尝试制作它们的内部副本.这导致它尝试并调用复制构造函数.但在我的例子中,我希望能够将新对移动到res,并确保不会制作副本.我认为除非std::pair自己在内部定义了以下构造函数,否则这是不可能的:
pair(T1&& t1, T2&& t2) : first(std::move(t1)), second(std::move(t2))
Run Code Online (Sandbox Code Playgroud)
但它没有,至少在我使用的编译器上没有(gcc 4.3.2).这可能是因为我的编译器是简单地外的日期,而事实上新版本将拥有这一举动感知构造.但是我对移动语义的理解目前有点不稳定,所以我不确定我是否只是在这里忽略了一些东西.那么,我是否正在努力实现,而不是实际重新实现std::pair?或者我的编译器是否已过时?
很抱歉,如果之前已经询问过,但据我所知,在C++ 11中,std::vector有一个移动构造函数,因此在某些情况下复制成本几乎没有,比如按值返回一个.但是,如果我有这样的类,使用vector作为成员变量:
class MyClass {
public:
MyClass() { }
MyClass(const MyClass& rhs) { }
// other interfaces
private:
std::vector<int> myvec;
// implementation
};
Run Code Online (Sandbox Code Playgroud)
并且有一个函数可以按值返回其中一个,例如
MyClass somefunc() {
MyClass mc;
// fill mc.myvec with thousands (maybe even millions) of ints
return mc;
}
Run Code Online (Sandbox Code Playgroud)
即使本身对移动构造函数一无所知,是否mc.myvec会调用移动构造函数和std::vector利用MyClass移动构造函数?或者是否vector要调用复制构造函数,并且int必须逐个复制所有数千个(甚至数百个)的复制构造函数?
我花了大量的时间来摆弄Visual Studio中的complilation错误.我已经将代码提炼到下面的小编译示例中,并在IdeOne上尝试了它并得到了同样的错误,你可以在这里看到.
我想知道为什么以下代码尝试调用B(const B&)而不是B(B&&):
#include <iostream>
using namespace std;
class A {
public:
A() : data(53) { }
A(A&& dying) : data(dying.data) { dying.data = 0; }
int data;
private:
// not implemented, this is a noncopyable class
A(const A&);
A& operator=(const A&);
};
class B : public A { };
int main() {
B binst;
char* buf = new char[sizeof(B)];
B* bptr = new (buf) B(std::move(binst));
cout << bptr->data << endl;
delete[] buf; …Run Code Online (Sandbox Code Playgroud) 我试图为没有复制构造函数的类实现移动构造函数.我收到一个错误,该类的成员的默认构造函数丢失.
这是一个简单的例子来说明这一点:
struct A {
public:
A() = delete;
A(A const&) = delete;
A(A &&a) {}
};
struct B {
A a;
B() = delete;
B(B const&) = delete;
B(B &&b) {}
};
Run Code Online (Sandbox Code Playgroud)
试着编译这个,我得到:
move_without_default.cc: In constructor ‘B::B(B&&)’:
move_without_default.cc:15:11: error: use of deleted function ‘A::A()’
B(B &&b) {}
^
move_without_default.cc:6:2: note: declared here
A() = delete;
^
Run Code Online (Sandbox Code Playgroud)
为什么这是一个错误?有什么办法吗?