例如,以下移动构造函数在没有&&(rvalue引用)的情况下工作:
Obj::Obj(Obj& obj) : elem { obj.elem }, data(obj.data) {
obj.elem = nullptr;
obj.data = 0;
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么有必要......
这是我获得大部分信息的地方:http://en.cppreference.com/w/cpp/language/move_constructor
显然,这些是隐式生成的移动构造函数的工作条件:
default我的问题是:
我更倾向于遵循三条规则并手动创建析构函数,复制和移动构造函数,以及复制和移动赋值运算符,但我只是对这个隐式运算符感到好奇.
所以,代码第一:
#include <iostream>
#include <utility>
struct X{
int i;
void transform(){}
X() :i(0){std::cout<<"default\n";}
X(const X& src): i(src.i){std::cout<<"copy\n";}
X(X&& msrc) :i(msrc.i){msrc.i=0;std::cout<<"move\n";}
};
X getTransform(const X& src){
X tx(src);
tx.transform();
return tx;
}
int main(){
X x1;// default
X x2(x1); // copy
X x3{std::move(X{})}; // default then move
X x41(getTransform(x2)); // copy in function ,then what?
X x42(std::move(getTransform(x2))); // copy in funciton, then move
X x51( (X()) );//default, then move? or copy?
// extra() for the most vexing problem
X x52(std::move(X())); //default …Run Code Online (Sandbox Code Playgroud) 我正在阅读C++ 11,我有以下问题.假设我有以下粗略代码
class foo
{
public:
foo()
{std::cout << "Regular constructor \n";}
foo(const foo& a)
{std::cout << "Copy constructor \n";}
foo& operator=(const foo& a)
{std::cout << "Copy Assignment operator \n";}
foo(foo&& a)
{
std::cout << "Move constructor \n";
}
foo& operator=(foo&& a)
{std::cout << "Move Assignment operator \n";}
int a;
};
foo myfunction()
{
foo d;
d.a =120;
return d;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我做这样的事情
foo a = myfunction();
Run Code Online (Sandbox Code Playgroud)
我知道将调用move构造函数,因为myfunction()返回一个rvalue类型.现在我注意到如果我从我的类中删除移动构造函数代码,则调用复制构造函数.我的问题是为什么会发生这种情况?如果myfunction的返回类型是foo &&并且复制构造函数接受foo,那么为什么要调用复制构造函数?我正在使用Vs2012.
下面的代码段似乎没问题,我相信声明A a(std::move(b).toA());会main()调用隐式声明的类的移动构造函数A,因为A它没有用户定义的复制构造函数,它没有用户定义的复制赋值运算符,它没有用户定义的移动赋值运算符,也没有用户定义的析构函数(参见§12.8/ 9 N4140).但是,当我取消注释下面的移动构造函数时A(A&&) { std::cout << "move A" << '\n'; },我收到了Illegal instruction消息.查看实例.为什么是这样?
#include <iostream>
#include <memory>
class A {
public:
// A(const A&) { std::cout << "copy A" << '\n'; }
// A(A&&) { std::cout << "move A" << '\n'; }
A(std::unique_ptr<int>&& u_ptr) : u_ptr(std::move(u_ptr)) {}
const int& getInt() { return *u_ptr; }
private:
std::unique_ptr<int> u_ptr;
};
class B {
public:
B(int u_ptr) : u_ptr(new …Run Code Online (Sandbox Code Playgroud) 如果我使用a unique_ptr<T>来构建一个pimpl类,我理解调用T析构函数的编译器生成的函数需要T是一个完整的类型.但是pimpl类的移动构造函数呢?编译器生成的版本只调用了unique_ptr移动构造函数.该功能不会破坏任何东西.此外,pimpl类生成的移动构造函数是隐式的noexcept,因此它的主体不可能抛出异常,导致它必须退出并销毁unique_ptr子对象.
看起来好像下面的代码应该编译:
#include <memory>
class Widget { // has implicit move ctor
struct Impl;
std::unique_ptr<Impl> pImpl;
};
int main()
{
Widget *pw1 = nullptr;
new Widget(std::move(*pw1)); // call move ctor. Rejected by
} // gcc, clang, and MSVC
Run Code Online (Sandbox Code Playgroud)
正如评论所说,这个代码被所有gcc,clang和MSVC拒绝.每个人抱怨对不完整类型的操作无效.这是标准要求的吗?如果是这样,那是哪一部分
请注意,此处的问题是编译,因此上述代码由于取消引用空pw1指针而未定义的运行时行为无关紧要.出于同样的原因,new在最后一个语句中调用引起的内存泄漏并不重要.
是不是UB移动 - 通过放置新建一个对象?
假设我有这段代码:
class Foo {
public:
Foo() { foo_ = new int; }
~Foo() { delete foo_; }
Foo(Foo &&f) {
foo_ = std::swap(f.foo_, foo_);
}
private:
int* foo_;
}
void bar() {
void* pMem = malloc(sizeof(Foo));
Foo f1;
// move-construct with placement new:
new((Foo*)pMem) Foo(std::move(f1)); // f2 in *pMem
// now f1 will contain a pointer foo_ of undefined value
// when exiting scope f1.~Foo(){} will exhibit UB trying to delete it
}
Run Code Online (Sandbox Code Playgroud)
如果不明显,f1的成员foo_将在构造第二个foo后通过放置new和move构造得到一个未定义的值(这个未定义的值来自未初始化的Foo f2在其move-constructor中的foo_,因为值是交换的) …
我有一个包含4个构造函数的类,函数如下:
using namespace std;
class ABC {
public:
ABC() {
cout << "ABC()\n";
}
ABC(int) {
cout << "ABC(int)\n";
}
ABC(ABC&) {
cout << "ABC(&)\n";
}
ABC(ABC&&) {
cout << "ABC(&&)\n";
}
};
void ff(ABC t) { }
Run Code Online (Sandbox Code Playgroud)
请帮我解释一些对我来说很奇怪的行为(我使用MSVC 2016进行编译):
1)为什么我收到警告C4930:"'ABC a1(ABC(__ cdecl*)(void))':未调用prototyped函数(是一个变量定义?)",使用以下代码:
void main() {
ABC a1(ABC());
ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)
在执行时,我希望得到以下输出:
ABC()
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)
但我真正得到的是
ABC(int)
Run Code Online (Sandbox Code Playgroud)
2)现在,如果我改为
void main() {
ABC a1(ABC(5));
ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)
没有更多的警告.但在执行时,我期望得到的是
ABC(int)
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)
但我真正得到的是
ABC(int)
ABC(int)
Run Code Online (Sandbox Code Playgroud)
3)现在
void main() {
ABC( ABC() ); …Run Code Online (Sandbox Code Playgroud) 我编写了以下代码来演示移动构造。但是即使我使用了 std::move(),也没有调用移动构造函数。有人可以看看这里有什么问题。
#include "point.hpp"
using namespace std;
class point;
d2point add_point(d2point&& p1, d2point&& p2)
{
cout << "inside add point function" << endl;
d2point z;
z.setX(p1.getX() + p2.getX());
z.setY(p1.getY() + p2.getY());
return z;
}
int main()
{
d2point x(2,3);
d2point y(2,3);
d2point z = add_point(move(x), move(y));
z.print_point();
x.print_point();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以下是来自point.hpp的代码
using namespace std;
class point
{
private:
int x;
public:
point(){cout << "point default constructor gets called" << endl;}
point(int x){ cout << "point param constructor gets called" …Run Code Online (Sandbox Code Playgroud) 我有一个类,它的负载非常重,因此创建/复制/移动此类的实例非常昂贵。由于应用程序完成初始化后它们不会改变,因此无需创建此类的临时对象。我只需要在容器(std::map)中缓存对象,并在需要时提供“常量引用”。
必须强调的一点是,我正在寻找一种解决方案,可以在将对象添加到容器之前避免双重创建或不必要的复制(我不认为像 @getsoubl 提出的解决方案可以解决问题,因为它不会消除双重创建或不必要的复制)。
因此,我想将构造函数方法安排到类主体的“私有/受保护”部分,以禁止在“工厂方法”之外进行任何创建/复制/移动。以下是我的原始解决方案:
class MyClass {
public:
// methods of the class
static const MyClass & findObject( int iKey ) {
auto pair = mapObjects.try_emplace( iKey, iKey );
if ( pair.second )
cout << "New object has been created" << endl;
return pair.first->second;
};
// deleted
MyClass() = delete;
MyClass( MyClass & ) = delete;
MyClass( MyClass && ) = delete;
MyClass( const MyClass & ) = delete;
MyClass( const MyClass && ) = delete;
MyClass …Run Code Online (Sandbox Code Playgroud) c++ ×10
move-constructor ×10
c++11 ×8
constructor ×3
copy ×1
emplace ×1
factory ×1
move ×1
unique-ptr ×1