2012-07-25 52 views
2

我有以下代码:为什么使用字符串的复制构造函数?

class TestClass 
{ 
public: 
    TestClass(){}; 

    std::string GetTestString() 
    { 
    return (mTestString); 
    } 
    void SetTestString(const std::string& rTestString) 
    { 
    mTestString = rTestString; 
    } 

private: 
    std::string mTestString; 
}; 

TestClass* pGlobalVar; 

void SomeFunction(TestClass MyClass) 
{ 
    pGlobalVar->SetTestString("cba"); 
    std::cout << "Changed string: " << pGlobalVar->GetTestString() << std::endl; 
    std::cout << "Copied string: " << MyClass.GetTestString() << std::endl; 

} 

int main() 
{ 
    pGlobalVar = new TestClass(); 
    pGlobalVar->SetTestString("abc"); 
    std::cout << "Original string: " << pGlobalVar->GetTestString() << std::endl; 
    SomeFunction(*pGlobalVar); 
    delete (pGlobalVar); 
} 

此输出以下:

Original string: abc 
Changed string: cba 
Copied string: abc 

,因为我没有定义我的类定义拷贝构造函数,我希望一个单位的副本将作出,包括std::string中的指针。显然,虽然使用std::string拷贝构造函数,但由于对原始字符串的更改不会更改副本。

任何人都可以向我解释为什么它没有制作平面复制?

我在Linux上使用GCC 4.4.6。

+1

'std :: string'被设计成(至少就复制而言)它的行为类似于int。如果成员'mTestString'的类型为'int',那么'pGlobalVar-> mTestString'不会被修改为调用'SomeFunction'。按照设计,'std :: string'也是如此。这是C++非常理想的特性。 – 2012-07-25 08:47:39

回答

5

,因为我没有定义我的课拷贝构造函数,我希望一个单位的副本会作出

既然你没有定义拷贝构造函数,C++为你做。

自动生成的拷贝构造函数调用其所有成员变量(如果它们有一个)的构造函数。

类似地,自动生成的构造函数调用其所有成员的构造函数,并且析构函数调用其所有成员的析构函数。

+0

严格来说,所有的类都声明了一个拷贝构造函数。具有非POD成员的类型不是声明或定义该构造函数的先决条件。 (你看起来像是这样,但也许这不是你的意图。) – 2012-07-25 08:56:47

+0

@Luc我没有意识到这一点。你能否引用标准中的相关段落?毕竟,POD类没有正规的构造函数,只有初始化器。 – 2012-07-25 09:03:23

+1

12.8复制和移动类对象[class.copy]第7段:“如果类定义没有明确声明复制构造函数,则隐式声明它。[...]”你可能想到的是一个特殊的成员可能是微不足道的,例如在'struct foo {int i; }'。(仍然允许编写static_cast (&foo :: operator =)'然而(第12节第2段) - 很难说没有复制赋值运算符。 – 2012-07-25 09:13:23

5

因为我没有为我的类定义一个拷贝构造函数,所以我希望能够制作一个平面拷贝,包括std :: string中的指针。

不,隐式生成的拷贝构造函数会使用它的拷贝构造函数复制每个数据成员(和基础子对象)(如果它有一个拷贝构造函数的话)。

任何人都可以向我解释为什么它没有平面复制?

因为那样会很糟糕。一个类定义了一个复制构造函数,因为它必须以某种方式复制;在std::string的情况下,它必须创建一个新的缓冲区。如果新字符串只保存了另一个指针的副本,那么两者都会认为它们拥有相同的缓冲区,并且两者都会在销毁它们时尝试释放它。

相关问题