除了显式之外,在 C++ 中创建隐式对象的方法有很多。几乎所有这些都使用对象类的复制构造函数。请记住:隐式复制可能需要T
在范围内声明类型的复制构造函数和/或赋值运算符,public
具体取决于复制发生的位置。
所以当然:
a)在堆栈中显式创建一个全新的对象:
T object(arg);
b) 显式复制现有对象:
T original(arg);
...
T copy(original);
如果T
类没有定义复制构造函数,则编译器创建默认实现。它尝试创建传递对象的精确副本。这并不总是程序员想要的,因此自定义实现有时可能很有用。
c) 在堆中显式创建一个全新的对象:
T *ptr = new T(arg);
d) 隐式创建一个全新的对象,它的构造函数只接受一个参数并且没有explicit
修饰符,例如:
class T
{
public:
T(int x) : i(x) {}
private:
int i;
}
...
T object = 5; // actually implicit invocation of constructor occurs here
e) 按值传递给函数的对象的隐式复制:
void func(T input)
{
// here `input` is a copy of an object actually passed
}
...
int main()
{
T object(arg);
func(object); // copy constructor of T class is invoked before the `func` is called
}
f) 按值处理的异常对象的隐式复制:
void function()
{
...
throw T(arg); // suppose that exception is always raised in the `function`
...
}
...
int main()
{
...
try {
function();
} catch (T exception) { // copy constructor of T class is invoked here
// handling `exception`
}
...
}
g) 使用赋值运算符创建新对象。我没有使用“复制”这个词,因为在这种情况下,特定类型的赋值运算符实现很重要。如果未实现此运算符,则默认实现由编译器创建,顺便说一句,它与默认复制构造函数具有相同的行为。
class T
{
T(int x) : i(x) {}
T operator=() const
{
return T(*this); // in this implementation we explicitly call default copy constructor
}
}
...
int main()
{
...
T first(5);
T second = first; // assingment operator is invoked
...
}
嗯,这就是我不用看 Stroustrup 的书就能记住的。可能是错过了什么。
在我写这篇文章的时候,一些答案被接受了,所以我在这一点上停下来。愿我列出的细节有用。