我有这个下面的程序,我通过引用函数传递一个向量myFunc,在这个函数里面,我向向量添加了一些元素.
我没有释放用new创建对象,现在忽略由此引起的内存泄漏.
后myFunc()执行完成我打印变量构造函数和析构函数知道多少次的构造函数和析构函数是如何调用.
输出是:
Before Exiting 5 7
Run Code Online (Sandbox Code Playgroud)
我创建了5个对象,以便ctor为5.但为什么dtor 7呢?额外的两个计数从何而来?我错过了什么吗?
#include
#include
using namespace std;
static int ctor = 0;
static int dtor = 0;
class MyClass
{
public:
MyClass(int n)
{
i = n;
ctor++;
// cout << "Myclass ctor " << ctor << endl;
}
~MyClass()
{
dtor++;
// cout << "Myclass dtor" << dtor << endl;
}
private:
int i;
};
void myFunc(vector<MyClass> &m);
void myFunc(vector<MyClass> &m) …Run Code Online (Sandbox Code Playgroud) 我正在阅读Mark Joshi的C++ Design Patterns and Derivatives Pricing,并在C++ 11中实现他的代码.在我讨论虚拟拷贝构造函数的第4章之前,一切都进行得很顺利.
PayOffDoubleDigital thePayOff(Low, Up);
VanillaOption theOption(thePayOff, Expiry);
Run Code Online (Sandbox Code Playgroud)
这里的问题是VanillaOption包含对的引用thePayOff.如果是这种情况并且有人修改了thePayOff,则theOption可以在不知情的情况下修改行为.他建议的解决方案是在PayOffDoubleDigital基类中创建一个虚拟拷贝构造函数,PayOff以便theOption包含它自己的副本:
virtual PayOff* clone() const = 0;
Run Code Online (Sandbox Code Playgroud)
然后在每个继承的类中定义:
PayOff* PayOffCall::clone() const
{
return new PayOffCall(*this);
}
Run Code Online (Sandbox Code Playgroud)
回归新事物让我觉得C++ 11可能不合适.那么使用C++ 11处理这个问题的正确方法是什么?
如果我没有为C++类提供显式的析构函数,因为我确信编译器提供的默认析构函数是我所有类的需求,那很好吗?或者这被认为是不好的做法?
我无法理解自动添加默认ctors背后的基本原理.特别是我觉得非常尴尬,每次我只需要添加一个空的虚拟析构函数,仅此而已,我放松了移动的东西,但添加它们我松散了副本和默认的东西,所以我最终添加所有这些代码:
virtual ~SomeClass(){} // you are the guilty!
//virtual ~SomeClass() = default // would be the same
SomeClass(SomeClass&&) = default; // no more auto-added
SomeClass& operator=(SomeClass&&) = default; // no more auto-added
SomeClass(const SomeClass&) = default; // but with the moves defined,
SomeClass& operator=(const SomeClass&) = default; // I'm now missing the copy
SomeClass(){} // and the default as well
Run Code Online (Sandbox Code Playgroud)
我确信有一个理由让我的课程变得丑陋,让我想要一个邪恶的宏观,我只是想知道它感觉更舒服.
我读完了Thomas Becker的"C++ Rvalue References".关于Rvalues和Rvalue参考,我有几个问题.
假设我有一个简单的数组类:
template <class T>
MyArray
{
...
T* m_ptr; // Pointer to elements
size_t m_count; // Count of elements
};
Run Code Online (Sandbox Code Playgroud)
进一步假设它提供:
#if(__cplusplus >= 201103L)
MyArray(MyArray&& t)
: m_ptr(std::move(t.m_ptr)), m_count(std::move(t.m_count))
{
t.m_ptr = NULL;
t.m_count = 0;
}
MyArray operator=(MyArray&& t)
{
std::swap(*this, t);
return *this;
}
#endif
Run Code Online (Sandbox Code Playgroud)
现在,假设我有一个不添加新数据成员的派生类:
MyImprovedArray : public MyArray
{
...
};
Run Code Online (Sandbox Code Playgroud)
需要什么MyImprovedArray?
它需要MyImprovedArray(MyImprovedArray&&)和MyImprovedArray& operator=(MyImprovedArray&&)吗?如果是这样,它只需要执行基类std::move吗?或者它也需要执行std::swap吗?
MyImprovedArray(MyImprovedArray&& t)
: MyArray(t) …Run Code Online (Sandbox Code Playgroud) 我正在使用C++进行面向对象编程的课程.
在我们的文中它说,
如果我们不声明复制构造函数,编译器会插入实现浅复制的代码.如果我们不声明赋值运算符,则编译器会插入实现浅赋值的代码.
我想知道的是,这实际上是否真实,实际调用了编译器机制的内容,以及它是如何工作的.
这不是关于复制构造函数的问题,而是关于编译器行为.
编辑>更多背景
按文本定义复制构造函数:
复制构造函数的定义包含逻辑
- 在所有非资源实例变量上执行浅拷贝
- 为每个新资源分配内存
- 将数据从源资源复制到新创建的资源
资源由文本定义
对象在运行时分配的内存表示该对象类的资源.
管理此资源需要额外的逻辑,这对于不访问资源的简单类来说是不必要的.这种额外的逻辑确保了对资源的正确处理,通常称为深度复制和分配.
union是用户定义的数据或类类型,在任何给定时间,它只包含其成员列表中的一个对象.假设需要动态分配所有可能的候选成员.对于Eg.
// Union Destructor
#include <string>
using namespace std;
union Person
{
private:
char* szName;
char* szJobTitle;
public:
Person() : szName (nullptr), szJobTitle (nullptr) {}
Person (const string& strName, const string& strJob)
{
szName = new char[strName.size()];
strcpy (szName, strName.c_str());
szJobTitle = new char [strJob.size()];
strcpy (szJobTitle, strJob.c_str()); // obvious, both fields points at same location i.e. szJobTitle
}
~Person() // Visual Studio 2010 shows that both szName and szJobTitle
{ // points to same location.
if (szName) {
delete[] …Run Code Online (Sandbox Code Playgroud) 就我的理解,五法则是指导性法则。尽管如此,我已经看到编译器在某些情况下可能会隐式删除函数。例如,当定义一个 move-ctor' 时,复制分配/复制 ctor' 将被删除。
我想知道是否有提到的更多场景。换句话说,自定义函数在哪些场景下可以隐式删除其他函数?
谢谢
编辑:
参考一些涵盖该主题的来源也可以!
我接受的答案读这里的是:
[a]不会为显式声明移动构造函数或移动赋值运算符的类生成复制构造函数和复制赋值运算符
我注意到(g ++ 4.7.2),如果你定义一个移动构造函数,它将与例如一起使用push_back(),而如果你所做的只是= delete复制构造函数,你就不会得到一个隐式移动构造函数 - 你得到一个错误. [...这让我想知道如果你没有明确地做任何事情,实际使用哪一个(移动或复制)...]
然而,本次网上参考不做出关于拷贝构造函数相同的明确承诺不会在定义转移构造函数被隐式定义.
所以我的问题是,标准保证的第一个报价(包括"或")?我宁愿,一些类这就需要一个明确的析构函数,只需移动构造函数和(删除)家移动运营商,完成"五规则",靠的是隐含的复制方法不被定义.如果我不能依赖它,那么我将不得不明确=delete它们 - 但这是很多潜在的冗余.
当且仅当我删除Foo的自定义析构函数时,以下代码才会编译.
struct Foo {
std::unique_ptr <int> bar;
~Foo (void) {} // This Line
};
std::vector <Foo> foos;
foos.push_back (Foo ());
Run Code Online (Sandbox Code Playgroud)
以下是我认为我对这种情况的理解:
它失败,因为unique_ptrs无法复制,并std::vector::push_back (thing)调用thing's复制构造函数.如果我编写Foo一个明确移动的自定义复制构造函数bar,那么一切都会好的.
但是,禁用This Line将导致代码编译.
我想,这应该无法编译,即使没有This Line,因为我仍然在尝试push_back一个unique_ptr.
为什么没有自定义析构函数就能成功,为什么添加自定义析构函数会导致它失败?
编辑:gcc -std=gnu++11在Debian Linux 64位上使用
c++ ×10
c++11 ×6
constructor ×2
destructor ×2
default ×1
rvalue ×1
shallow-copy ×1
stl ×1
unions ×1