2017-07-25 70 views
1

上下文:嵌入式编程和初始化列表细微差别,尤其是我认为应该调用复制构造函数的细微差别。C++初始化指针/参考/复制细微差别

问题:在另一个类的初始值设定项列表中初始化一个值持有成员变量的类的实例化是否会调用复制构造函数? 下面提供了一个示例,其中TestClassCopy有一个由值保存的成员变量TestMember,而不是指针或引用。在提供的示例中,这个cppreference page似乎没有充分说明这一点。

红利问题:初始化程序列表中调用的复制构造函数是否会产生任何时间/空间性能影响?看起来像编译器应该能够优化,如果C++规范允许。


下面的代码(生成与VS2015工具链测试):

TestMember.h(未示出TestMember.cpp空间原因)

#pragma once 

#include <stdint.h> 

class TestMember { 
public: 
    TestMember(uint8_t); 

private: 
    uint8_t m_value; 
}; 

TestClassCopy.h

#pragma once 

#include "test_member.h" 

class TestClassCopy { 
public: 
    TestClassCopy(); 
    virtual ~TestClassCopy(); 

private: 
    TestMember m_member; 
}; 

TestClassCopy.cpp

#include "test_class_copy.h" 

TestClassCopy::TestClassCopy() : 
    m_member(TestMember(255)) { // invokes copy constructor yes? 
} 

TestClassCopy::~TestClassCopy() { 
} 

为了完整,其他的事情,我可能会做出假设我不应该:

对于初始化成员指针到TestMember,一个“新”列表和在析构函数中的'删除'应该是足够的。

对于成员引用,我的理解是,如果将引用传递给构造函数,您可以将其分配(因为生命周期在初始化程序列表之外进行管理),因此存在更多细微差别。 但是,如果TestMember在初始化程序列表(在引用中)实例化,那么这是一个禁止,因为初始化完成后TestMember临时消失。

TestMemberReference.h

#pragma once 

class TestMember; 

class TestClassReference { 
public: 
    TestClassReference(); 
    virtual ~TestClassReference(); 

private: 
    TestMember& m_member; 
}; 

TestMemberReference。CPP

#include "test_class_reference.h" 

#include "test_member.h" 

TestClassReference::TestClassReference() : 
    m_member(TestMember(255)) { // ew, don't do this; TestMember temporary will go out of scope 
} 

TestClassReference::~TestClassReference() { 
} 
+0

在你的第一个例子中,[copy is elided](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and返回值优化),则不执行复制。 – CoryKramer

+0

你总是可以在复制构造函数 –

+0

@CoryKramer中放置打印语句或断点,完美的是我一直在寻找的谢谢。我想这意味着你说'是的,复制构造函数可以被调用,但由于省略,它可能会或可能不会取决于编译器优化设置等'。 PS。如果你想创建一个完整的答案,我可以接受它作为答案。 – azydevelopment

回答

0

cppreference page似乎并不在于cppreference页说提供

实施例充分地覆盖该“初始化通过使用类或标识符direct initialization命名基部或构件”如果你点击它,你可以阅读,从C++ 17开始,

如果初始值设定项是一个prvalue表达式SE CV-非限定类型是相同的类为T,初始化表达本身,而该临时从它物化,用于初始化目标对象:看到复制省略

所以答案是:在C + +17没有拷贝构造函数被调用。在C++ 17之前,技术上可以调用复制构造函数,但复制elision消除了该调用。你仍然可以观察它,作为证明,通过编写你的例子g++ -fno-elide-constructors -O0 -std=c++14