在C++中,我不清楚从复制赋值运算符返回引用的概念.为什么复制赋值运算符不能返回新对象的副本?另外,如果我上课A,还有以下内容:
A a1(param);
A a2 = a1;
A a3;
a3 = a2; //<--- this is the problematic line
Run Code Online (Sandbox Code Playgroud)
的operator=定义如下:
A A::operator=(const A& a)
{
if (this == &a)
{
return *this;
}
param = a.param;
return *this;
}
Run Code Online (Sandbox Code Playgroud) c++ operator-overloading copy-constructor assignment-operator
这是一个初学者的问题,但我很长一段时间没有做过C++,所以这里......
我有一个包含动态分配数组的类,比方说
class A
{
int* myArray;
A()
{
myArray = 0;
}
A(int size)
{
myArray = new int[size];
}
~A()
{
// Note that as per MikeB's helpful style critique, no need to check against 0.
delete [] myArray;
}
}
Run Code Online (Sandbox Code Playgroud)
但现在我想创建一个动态分配的这些类的数组.这是我目前的代码:
A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
arrayOfAs[i] = A(3);
}
Run Code Online (Sandbox Code Playgroud)
但这种情况非常糟糕.因为在循环迭代完成时,A(通过A(3)调用)创建的新对象会被破坏for,这意味着myArray该A实例的内部delete []变为-ed.
所以我认为我的语法必定是非常错误的?我想有一些看起来像矫枉过正的修复,我希望避免:
A …如果我覆盖operator=,复制构造函数会自动使用new运算符吗?同样,如果我定义了一个拷贝构造函数,会operator=自动"继承"拷贝构造函数的行为吗?
c++ constructor operators copy-constructor assignment-operator
假设我有这样的POD类型:
struct A {
char a;
int b;
};
Run Code Online (Sandbox Code Playgroud)
在我的系统上,sizeof(A) == 8即使sizeof(char) == 1和sizeof(b) == 4.这意味着数据结构有3个未使用的字节.
现在假设我们这样做
A x = ...;
A y =x;
Run Code Online (Sandbox Code Playgroud)
题:
难道是保证所有8个字节的x和y将是相同的,即使是那些3分未使用的?
同样,如果我将某些A对象的底层字节转移到另一个不理解其含义或结构的程序,并将它们视为一个8字节的数组,那么其他程序可以安全地比较两个As的相等吗?
注意:在使用gcc 7的实验中,似乎会复制这些字节.我想知道这是否有保证.
我听说C++有一些叫做"转换构造函数"或"转换构造函数"的东西.这些是什么,它们的用途是什么?我在这段代码中看到了它:
class MyClass
{
public:
int a, b;
MyClass( int i ) {}
}
int main()
{
MyClass M = 1 ;
}
Run Code Online (Sandbox Code Playgroud) 为什么人们定义私有拷贝构造函数?
何时使复制构造函数和赋值运算符私有化是一个好的设计?
如果有哪个是指针或处理到一个唯一的对象(如文件名)类没有成员,然后笏其他情况下都存在,其中私人拷贝构造函数是一个好主意?
同样的问题适用于赋值运算符.鉴于大多数C++围绕复制对象并通过引用传递,是否有任何涉及私有拷贝构造函数的好设计?
当我正在阅读boost/shared_ptr.hpp时,我看到了这段代码:
// generated copy constructor, destructor are fine...
#if defined( BOOST_HAS_RVALUE_REFS )
// ... except in C++0x, move disables the implicit copy
shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
{
}
#endif
Run Code Online (Sandbox Code Playgroud)
注释"生成复制构造函数,析构函数是否正常,除了在C++ 11中,移动禁用隐式副本"是什么意思?我们是否总是自己编写副本来防止C++ 11中出现这种情况?
鉴于由派生类的继承过多基类,这需要您通过基类指针,每个实体管理这些程序结构.当只知道基类指针时,是否有一种简单的方法来复制整个派生对象?
环顾四周似乎可能(如果非常繁琐)使用dynamic_cast调用来检查基类指针是否可以作为适当的派生类进行转换,然后使用派生类的复制构造函数复制它.然而,这并不是一个真正的最佳解决方案,部分原因是由于过度使用了dynamic_cast,而且它会让人感到头疼,难以维持和扩展.
我遇到的另一个更优雅的解决方案如下:
class Base
{
public:
Base(const Base& other);
virtual Base* getCopy();
...
}
class Derived :public Base
{
Derived(const Derived& other);
virtual Base* getCopy();
...
}
Base* Base::getCopy()
{
return new Base(*this));
}
Base* Derived::getCopy()
{
return static_cast<Base*>(new Derived(*this));
}
Run Code Online (Sandbox Code Playgroud)
然后通过调用getCopy()指向任何派生对象的Base类指针,仍然可以返回一个基类指针,但也复制了整个派生对象.这种方法感觉更易于维护,因为它只需要getCopy()在所有派生类中使用类似的函数,并且不需要针对所有可能的派生对象进行测试.
从本质上讲,这是明智的吗?或者有更好,更简洁的方式吗?
我曾经认为,当遵循最佳实践时,C++的对象模型非常强大.
就在几分钟前,我意识到我以前没有过.
考虑以下代码:
class Foo
{
std::set<size_t> set;
std::vector<std::set<size_t>::iterator> vector;
// ...
// (assume every method ensures p always points to a valid element of s)
};
Run Code Online (Sandbox Code Playgroud)
我写了这样的代码.直到今天,我还没有看到它的问题.
但是,考虑到它更多,我意识到这个类非常破碎:
它的copy-constructor和copy-assignment 复制里面的迭代器vector,这意味着它们仍然会指向旧的 set!毕竟新的不是真正的副本!
换句话说,我必须手动实现copy-constructor,即使这个类没有管理任何资源(没有RAII)!
这令我惊讶.我以前从未遇到过这个问题,我也不知道有什么优雅的方法来解决它.关于它的思考多一点,在我看来,那拷贝构造是默认不安全的 -事实上,在我看来那类应该不会是在默认情况下拷贝,但因为他们的实例变量之间的任何一种耦合的风险再现默认副本- 构造函数无效.
迭代器是否从根本上说不安全?或者,默认情况下类是否真的不可复制?
我在下面想到的解决方案都是不可取的,因为它们不会让我利用自动生成的复制构造函数:
考虑一个类层次结构,其中A是基类并B派生自A.
如果未定义复制构造函数B,编译器将合成一个.调用时,此复制构造函数将调用基类复制构造函数(即使是合成的构造函数,如果用户没有提供).
#include <iostream>
class A {
int a;
public:
A() {
std::cout << "A::Default constructor" << std::endl;
}
A(const A& rhs) {
std::cout << "A::Copy constructor" << std::endl;
}
};
class B : public A {
int b;
public:
B() {
std::cout << "B::Default constructor" << std::endl;
}
};
int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating …Run Code Online (Sandbox Code Playgroud) c++ ×10
copy-constructor ×10
constructor ×2
pointers ×2
boost ×1
c++11 ×1
destructor ×1
inheritance ×1
iterator ×1
operators ×1