以下代码是在Visual Studio 2012 Express for Windows Desktop中编译和运行的,作为学习练习.
#include <cstdio>
class X
{
public:
X() { printf("default constructed\n"); }
~X() { printf("destructed\n");}
X(const X&) { printf("copy constructed\n"); }
X(X&&) { printf("move constructed\n"); }
X & operator= (const X &) { printf("copy assignment operator\n"); }
};
X A() {
X x;
return x;
}
int main() {
{
A();
}
std::getchar();
}
Run Code Online (Sandbox Code Playgroud)
在禁用编译器优化(/ Od)的情况下编译时,结果输出表明析构函数被调用两次.考虑到只构造了一个对象,这是一个问题.为什么析构函数被调用两次?如果班级管理自己的资源,这不是一个问题吗?
default constructed
move constructed
destructed
destructed <<< Unexpected call
Run Code Online (Sandbox Code Playgroud)
我尝试了几个实验来尝试解释输出,但最终这些并没有导致任何有用的解释.
实验1:在使用优化(/ O1或/ O2)编译相同代码时,结果输出为:
default constructed
destructed …Run Code Online (Sandbox Code Playgroud) 如果我有一个管理一些动态内存的类(例如矢量类型)并且它已经有一个移动构造函数,为函数提供移动感知重载是否有意义,或者移动构造函数是否有意义照顾它?
例如,我应该使用Class&&变量重载哪些(如果有的话):
// the move-aware overload for all of these would be
// void FuncX(Class&&);
void Func1(Class);
void Func3(Class&); // doesn't make a local copy
void Func4(Class&); // makes a local copy
void Func5(Class const);
void Func7(Class const&); // doesn't make a local copy
void Func8(Class const&); // makes a local copy
Run Code Online (Sandbox Code Playgroud)
他们中的任何一个都失去了优化机会,因为我没有提供移动感知变体吗?
我有以下代码:
#include <iostream>
class foo_class {
std::string value;
public:
foo_class(const foo_class& v) : value{v.value} {
std::cout << "copy constructor" << std::endl;
}
foo_class(foo_class&& v) : value{std::move(v.value)} {
std::cout << "move constructor" << std::endl;
}
~foo_class() {
std::cout << "destructor" << std::endl;
}
foo_class(std::string v) : value{std::move(v)} {
std::cout << "type constructor" << std::endl;
}
};
struct Data {
foo_class a;
foo_class b;
};
int main() {
std::string c = "3";
Data x{c,c+"3"};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
重要的是,我使用GCC和Clang(分别为4.8.2和3.4)和标志-fno-elide-constructors进行编译,因此我们不会忽略复制/移动构造函数.
执行结果如下: …
当我需要创建一个非可复制构造对象的数组时,我偶尔会遇到这种情况.例如:
std::vector<std::thread> thread_pool(NUM_CORES, std::thread(some_function));
Run Code Online (Sandbox Code Playgroud)
那会很方便.但是,std::vector填充构造函数似乎没有任何R值支持.它被定义为:
vector(
size_type count,
const T& value,
const Allocator& alloc = Allocator()
);
Run Code Online (Sandbox Code Playgroud)
但是拥有以下内容会非常方便:
vector(
size_type count,
T&& value,
const Allocator& alloc = Allocator()
);
Run Code Online (Sandbox Code Playgroud)
然后向量可以在内部分配必要的缓冲区大小,并使用placement new移动构造每个元素.
但是...... C++ 11标准(显然甚至是C++ 14标准)都没有提供这种功能.那么,现在 - 当我有一个线程向量时,我不得不说:
std::vector<std::unique_ptr<std::thread>> thread_pool(NUM_CORES);
/* now loop over vector and initialize elements one by one */
Run Code Online (Sandbox Code Playgroud)
有什么理由将这种能力排除在外吗?有危险吗?还是我看不到的一些问题?
我正在查看以下有关移动构造函数/赋值的示例:https: //msdn.microsoft.com/en-us/library/dd293665.aspx
我通过添加交换函数来修改它,以简化移动构造函数/赋值和复制赋值:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class MemoryBlock
{
public:
// Simple constructor that initializes the resource.
explicit MemoryBlock(size_t length)
: _length(length)
, _data(new int[length])
{
std::cout << "In MemoryBlock(size_t). length = "
<< _length << "." << std::endl;
}
// Destructor.
~MemoryBlock()
{
std::cout << "In ~MemoryBlock(). length = "
<< _length << ".";
if (_data != nullptr)
{
std::cout << " Deleting resource.";
// Delete the resource.
delete[] _data;
} …Run Code Online (Sandbox Code Playgroud) 是否有一种干净的方式来移动它的元素?就像是:
set<A> s {...};
vector<A> v;
for (const A& a : s)
v.push_back(move(const_cast<A&>(a)));
s.clear(); //undefined behavior?
Run Code Online (Sandbox Code Playgroud) 我是一个相当称职的C++用户(不是一个完整的菜鸟).我有一个充当资源句柄的类.这个类有一个移动构造函数和复制construtor被删除是有道理的:
struct Foo {
Foo (int i) : // For sake of example.
x(i)
{}
Foo (Foo && f) :
x(f.x)
{
f.x = 0; // 0 is special and means "moved from".
}
Foo (const Foo & f) = delete;
private:
int x;
};
Run Code Online (Sandbox Code Playgroud)
多年来我一直以货物崇拜的方式做这件事而且工作正常.现在我正试图用我的C++ 11用法加强装备.
我还有一个类,它保持了vector的Foo:
struct Bar { // (Constructor added below)
std::vector<Foo> foos;
};
Run Code Online (Sandbox Code Playgroud)
我想写一个构造函数,用于Bar调用者传入的位置vector<Foo>.我想将调用者提供的整个向量移入Bar.foos.我想通过使构造函数参数vector<Foo>&&而不是普通参数使调用者明确vector<Foo>&.这样,调用者必须std::move将vector插入到构造函数中.
int main (int …Run Code Online (Sandbox Code Playgroud) 我有一个名为explicitely删除的复制构造函数的类,比方说,NonCopyable.然后是一个类型Base1成员的类NonCopyable.而另一类Base2与Base1父.最后 - Derivative父母是一个阶级Base2.
由于NonCopyable是不可复制的,因此很明显Base1,Base2并且Derivative也是不可复制的.但似乎还有移动构造函数(和赋值运算符)已删除.
在这里测试一下:
以下行给出了这些错误:
Derived d1, d2 = std::move(d1);
GCC: 'Derived :: Derived(Derived &&)'被隐式删除,因为默认定义是不正确的:class Derived:
其余的错误只是声称Base1和Base2复制ctors被隐式删除,这并不奇怪MSVC:错误C2280:'Derived :: Derived(const Derived&)':尝试引用已删除的函数
在提供的链接中,还有注释行,它们给出了类似的错误.请取消注释以查看我想向您展示的更多错误(例如,未remove_if注释它会抱怨删除移动(在GCC上) /复制(在MSVC上)分配操作员).
我想要实现的是使Derivative(及其基础)可移动,但不可复制.
我正在使用Visual Studio 2015并获得与我提供的msvc链接完全相同的错误,但我不确定在rextester.com上使用什么版本的MSVC进行编译.
我也是应@Richard Critten的要求粘贴代码的:
class NonCopyable
{
public:
NonCopyable() { }
NonCopyable(const NonCopyable &) = delete;
NonCopyable & operator=(const …Run Code Online (Sandbox Code Playgroud) 我有一个用RAII编写的Array类(为了这个例子的目的,超简化):
struct Array
{
Array(int size) {
m_size = size;
m_data = new int[m_size];
}
~Array() {
delete[] m_data;
}
int* m_data = nullptr;
int m_size = 0;
};
Run Code Online (Sandbox Code Playgroud)
然后我有一个函数,它接受一个数组的引用并对它进行一些操作.我使用临时数组temp来执行处理,因为有几个原因我不能直接使用引用.完成后,我想将数据从临时数据传输到真实数据:
void function(Array& array)
{
Array temp(array.m_size * 2);
// do heavy processing on `temp`...
array.m_size = temp.m_size;
array.m_data = temp.m_data;
}
Run Code Online (Sandbox Code Playgroud)
显而易见的问题是temp在函数末尾超出范围:它的析构函数被触发,而后者又删除了内存.这种方式array将包含不存在的数据.
那么将数据所有权从一个对象"移动"到另一个对象的最佳方法是什么?
Considering only objects that are movable but non-copyable (e.g., std::thread or std::unique_ptr), I want to transfer the ownership of the resource such an object contains by passing it as an argument to a constructor. I'm comparing two approaches: the constructor taking the object by value vs. by rvalue reference.
As an example with std::thread, consider the following class Value whose constructor takes an std::thread by value:
#include <thread>
#include <utility>
struct Value {
Value(std::thread th): th_(std::move(th)) …Run Code Online (Sandbox Code Playgroud) c++ ownership-semantics parameter-passing move-semantics c++11
move-semantics ×10
c++ ×9
c++11 ×9
inheritance ×1
memory ×1
set ×1
temporary ×1
vector ×1
visual-c++ ×1