Mik*_*ike 3 c++ constructor c++11 visual-studio-2012
我写了一段简单的代码来试用C++ 11的make_shared.当我打电话时,我不明白为什么
std::shared_ptr<MyClass> x = std::make_shared<MyClass>(MyClass());
Run Code Online (Sandbox Code Playgroud)
调用默认构造函数并调用移动构造函数.这看起来很好,因为移动构造函数不会创建副本.但是如果我注释掉MyClass的move构造函数的实现,它会调用默认的构造函数,然后是复制构造函数,这似乎打败了make_shared的目的.
#include <iostream>
#include <memory>
//-----------------------------------------------------------
class MyClass {
public:
// default constructor
MyClass() :
_data(0.0)
{
_data = (float)3.14;
std::cout << "MyClass::default constructor - data=" << _data << " ; class=" << this << std::endl;
};
// copy constructor
MyClass(const MyClass& input)
{
_data = input._data;
std::cout << "MyClass::copy constructor - data=" << _data << " ; class=" << this << std::endl;
};
// move constructor
MyClass(MyClass&& other)
{
std::cout << "MyClass::move constructor(before) - data=" << _data << " ; class=" << this << std::endl;
_swap(*this, other);
std::cout << "MyClass::move constructor(after) - data=" << _data << " ; class=" << this << std::endl;
};
// destructor
~MyClass()
{
std::cout << "MyClass::destructor - data=" << _data << " ; class=" << this << std::endl;
};
private:
// swap
void MyClass::_swap(MyClass& X, MyClass& Y)
{
std::swap(X._data, Y._data);
}
// members
float _data;
};
//-----------------------------------------------------------
int main()
{
std::shared_ptr<MyClass> x = std::make_shared<MyClass>(MyClass());
std::cout << std::endl << "Address for x: " << x << std::endl;
std::cout << std::endl << "Press Enter to exit." << std::endl;
std::cin.ignore();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面代码的输出是:
MyClass::default constructor - data=3.14 ; class=000000000019F860
MyClass::move constructor(before) - data=0 ; class=00000000003C3440
MyClass::move constructor(after) - data=3.14 ; class=00000000003C3440
MyClass::destructor - data=0 ; class=000000000019F860
Address for x: 00000000003C3440
Press Enter to exit.
MyClass::destructor - data=3.14 ; class=00000000003C3440
Run Code Online (Sandbox Code Playgroud)
如果我注释掉移动构造函数,则输出为:
MyClass::default constructor - data=3.14 ; class=000000000016FA00
MyClass::copy constructor - data=3.14 ; class=00000000001B3440
MyClass::destructor - data=3.14 ; class=000000000016FA00
Address for x: 00000000001B3440
Press Enter to exit.
MyClass::destructor - data=3.14 ; class=00000000001B3440
Run Code Online (Sandbox Code Playgroud)
也许我对make_shared的作用有一个缺陷.任何人都可以向我解释为什么会这样吗?
谢谢.
你打电话的时候:
std::shared_ptr<MyClass> x = std::make_shared<MyClass>(MyClass());
Run Code Online (Sandbox Code Playgroud)
这是发生的事情:
MyClass()创建内部实例(第一个构造函数调用 - 默认调用).MyClass()是暂时的.make_shared完美,转发你的临时MyClass的移动构造函数的MyClass,因为MyClass声明一个和临时可以通过右值引用的约束MyClass&&.(第二个构造函数调用 - 移动构造函数).现在,当您删除move-constructor时,会发生以下情况:
MyClass()创建内部实例(第一个构造函数调用 - 默认调用).MyClass()是暂时的.make_shared完美转发你的临时MyClass,但因为MyClass没有移动构造函数,而是临时由const MyClass&复制构造函数的引用绑定,因此复制构造函数被调用(第二个构造函数调用 - 复制构造函数).也就是说,传递给的参数std::make_shared实际上是构造函数的参数而不是实例本身.因此你应该写:
std::shared_ptr<MyClass> x = std::make_shared<MyClass>();
Run Code Online (Sandbox Code Playgroud)
例如,如果您有一个MyClass以下签名的构造函数:
MyClass(int x, float f, std::unique_ptr<int> p);
Run Code Online (Sandbox Code Playgroud)
然后你会说:
std::shared_ptr<MyClass> x
= std::make_shared<MyClass>(123, 3.14f, std::make_unique<int>(5));
Run Code Online (Sandbox Code Playgroud)
并make_shared保证这些参数将完美地转发给MyClass构造函数.
您可以将std::make_shared辅助函数视为如下所示:
template <typename T, typename... Args>
auto make_shared(Args&&... args) -> std::shared_ptr<T>
{
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
}
Run Code Online (Sandbox Code Playgroud)
注意:实际上make_shared还为连续内存块中的引用计数器分配空间,绑定析构函数,并执行其他魔术.上面的代码片段只是一个例子来说明参数本身会发生什么.
| 归档时间: |
|
| 查看次数: |
1149 次 |
| 最近记录: |