考虑一类需要复制的副本.副本中的绝大多数数据元素必须严格反映原始数据元素,但是有少数元素的状态不被保留且需要重新初始化.
从复制构造函数调用默认赋值运算符是不好的形式?
默认赋值运算符对于Plain Old Data(int,double,char,short)以及每个赋值运算符的用户定义类都表现良好.指针需要单独处理.
一个缺点是该方法使得赋值运算符瘫痪,因为不执行额外的重新初始化.也无法禁用赋值运算符的使用,从而通过使用不完整的默认赋值运算符打开用户创建损坏类的选项A obj1,obj2; obj2=obj1; /* Could result is an incorrectly initialized obj2 */.
a(orig.a),b(orig.b)...除了a(0),b(0) ...必须写之外,放宽要求是很好的.需要写入所有初始化两次会产生两个错误位置,如果double x,y,z要将新变量(例如)添加到类中,初始化代码需要在至少2个位置而不是1个位置正确添加.
有没有更好的办法?
在C++ 0x中有更好的方法吗?
class A {
public:
A(): a(0),b(0),c(0),d(0)
A(const A & orig){
*this = orig; /* <----- is this "bad"? */
c = int();
}
public:
int a,b,c,d;
};
A X;
X.a = 123;
X.b = 456;
X.c = 789;
X.d = 987;
A Y(X);
printf("X: %d %d %d %d\n",X.a,X.b,X.c,X.d); …Run Code Online (Sandbox Code Playgroud) 我的印象是阵列是不可复制的(或可分配的).
int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,0};
x = y; // Fails to compile
Run Code Online (Sandbox Code Playgroud)
但是当我在一个类中放入一个数组时,复制构造函数和赋值运算符工作(我会按预期说,但它不是我所期望的).
#include <iostream>
struct X
{
virtual ~X(){} // Just in case it was something to do with POD
// make sure its not a POD
int x[5];
};
int main()
{
X a;
a.x[0] = 0;
a.x[1] = 1;
a.x[2] = 2;
a.x[3] = 3;
a.x[4] = 4;
// Make a copy of a and test it
X b(a);
std::cout << a.x[0] << …Run Code Online (Sandbox Code Playgroud) 我想知道我是否误解了某些内容:复制构造函数是否std::string 不复制其内容?
string str1 = "Hello World";
string str2(str1);
if(str1.c_str() == str2.c_str()) // Same pointers!
printf ("You will get into the IPC hell very soon!!");
Run Code Online (Sandbox Code Playgroud)
这将打印出"你很快就会进入IPC地狱!" 它让我烦恼
这是正常的行为std::string吗?我在某处读到它通常会做一个深层复制.
但是,这可以按预期工作:
string str3(str1.c_str());
if(str1.c_str() == str3.c_str()) // Different pointers!
printf ("You will get into the IPC hell very soon!!");
else
printf ("You are safe! This time!");
Run Code Online (Sandbox Code Playgroud)
它将内容复制到新字符串中.
我是C++编程的新手,当我做一些C++程序时,我怀疑这就是为什么当我将一个对象作为参数传递给一个函数时调用复制构造函数的原因.请看我的下面的代码,我将一个类的对象作为参数传递给函数display(),但它调用复制构造函数然后控件正在触及display()函数,但我理解为什么它请帮助.
#include "stdafx.h"
#include <iostream>
using namespace std;
class ClassA
{
private:
int a, b;
public:
ClassA()
{
a = 10, b = 20;
}
ClassA(ClassA &obj)
{
cout << "copy constructor called" << endl;
a = obj.a;
b = obj.b;
}
};
void display(ClassA obj)
{
cout << "Hello World" << endl;
}
int main()
{
ClassA obj;
display(obj);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我试图使用C++ 11的构造函数继承功能.以下片段(从某处复制,我不记得从哪里)完全正常:
#include <iostream>
struct Base {
Base() : Base(0) {}
Base(int a) : Base(a, 0) {}
Base(int a, double b) { std::cout << "Base(" << a << "," << b << ")" << std::endl; }
};
struct Derived : Base {
using Base::Base;
Derived(const Derived& that) = delete; // This line is the culprit
};
int main(int argc, char* argv[]) {
Derived d1;
Derived d2(42);
Derived d3(42, 3.14);
}
Run Code Online (Sandbox Code Playgroud)
也就是说,直到添加注释标记的行为止; 因为那时所有地狱都破裂了:
> g++ -std=c++11 -o test test.cpp
test.cpp: In …Run Code Online (Sandbox Code Playgroud) 我在 type script 上有一堂课:
export class Child {
name:string;
age:number;
}
Run Code Online (Sandbox Code Playgroud)
我想强制类实例只具有类声明所具有的属性。
例如,如果我从 firebase 获取一个对象:
myFirebaseService.getChild(id).then(function(child){
var currentChild = new Child(child);
})
Run Code Online (Sandbox Code Playgroud)
所以当对象是:{name:"ben", color:"db"} 时,我希望结果是:
currentChild = {"name":"ben"}
Run Code Online (Sandbox Code Playgroud)
因为“颜色”不是“孩子”的领域。
我试过这个:
export class Child {
name:string;
age:number;
constructor(tempChild:Child = null) {
if (tempChild){
for (var prop in tempChild) {
this[prop] = tempChild[prop];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但它没有帮助。“currentChild”获取所有字段并将它们附加到类实例。
(当然,我可以使用以下代码:
export class Child {
name:string;
age:number;
constructor(tempChild:Child = null) {
if (tempChild){
this.nam = tempChild.name;
this.age =tempChild.ageÏ;
}
}
}
Run Code Online (Sandbox Code Playgroud)
,但我的真理课有很多字段,我想要短代码)
考虑以下示例:
struct Parent
{
Parent ();
Parent (const Parent &);
};
struct Child : public Parent
{
using Parent::Parent;
};
Parent p;
Child c (p);
Run Code Online (Sandbox Code Playgroud)
这是从以下问题中得出的:为什么“继承的构造函数不是从相同或派生类型的表达式初始化的候选对象”?
最初的问题是关于C ++ 11的。在C ++ 11中,有一些措辞阻止Child获取采用以下内容的构造函数const Parent&:
对于继承的构造函数候选集中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,除非具有用户声明的构造函数,否则该构造函数将隐式声明为具有相同的构造函数特性类中出现使用声明的相同签名。
N4429极大地改变了继承构造函数的规范,并被认为可追溯到C ++ 11(我认为?)。N4429的目的是使基类构造函数看起来像是派生类构造函数一样可见,而不是声明委派给基类构造函数的派生类构造函数。在N4429的第一个版本中,有以下措词,保留了C ++ 11的限制:
当using声明声明类从基类继承构造函数时,基类的默认构造函数,复制构造函数和move构造函数(如果有)将从引入的声明集中排除。
但是,在本文的更新版本P0136R0中,该措辞不再存在,并且没有给出原因的解释。该文件再次进行了修订,然后被合并为标准。因此,在C ++ 17中,我看不到任何阻止上述代码编译的规则。
尽管如此,GCC和Clang都拒绝了它。lang声:
继承的构造方法不是从相同或派生类型的表达式初始化的候选对象
但是,我无法在标准中找到类似这样的内容。
这段代码在C ++ 17中格式错误吗?如果是这样,为什么?
我偶然发现了下面的代码。该"DerivedFoo"案例在 MSVC 上产生的结果与在 clang 或 gcc 上产生的结果不同。即,clang 13 和 gcc 11.2 调用复制构造函数,Foo而 MSVC v19.29 调用模板化构造函数。我正在使用 C++17。
考虑到所有编译器都同意调用模板化构造函数的非派生情况("Foo"),我认为这是 clang 和 gcc 中的错误,而 MSVC 是正确的吗?或者我解释错误而 clang/gcc 是正确的?任何人都可以阐明可能发生的事情吗?
代码(https://godbolt.org/z/bbjasrraj):
#include <iostream>
using namespace std;
struct Foo {
Foo() {
cout << "\tFoo default constructor\n";
}
Foo(Foo const &) { cout << "\tFoo COPY constructor\n";
}
Foo(Foo &&) {
cout << "\tFoo move constructor\n";
}
template <class U>
Foo(U &&) {
cout << "\tFoo TEMPLATED constructor\n"; …Run Code Online (Sandbox Code Playgroud) 根据我的理解,我可以通过定义私有拷贝构造函数和赋值运算符来"禁用"复制和分配给我的对象:
class MyClass
{
private:
MyClass(const MyClass& srcMyClass);
MyClass& operator=(const MyClass& srcMyClass);
}
Run Code Online (Sandbox Code Playgroud)
但这有什么用呢?
它被认为是一种不好的做法吗?
如果您能够描述这种情况,我将不胜感激,以这种方式"禁用"赋值和复制构造函数是合理/有用的.
考虑以下程序:
#include <iostream>
#include <utility>
class T {
public:
T() { printf("address at construction: %zx\n", (uintptr_t)this); }
// T(const T&) { printf("copy-constructed\n"); } // helps
// T(T&&) { printf("move-constructed\n"); } // helps
// T(const T&) = default; // does not help
// T(T&&) = default; // does not help
};
T f() { return T(); }
int main() {
T x = f();
printf("address after construction: %zx\n", (uintptr_t)&x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时g++ -std=c++17 test.cpp给出以下输出(与之相同clang++):
address at …Run Code Online (Sandbox Code Playgroud) copy-constructor ×10
c++ ×9
c++17 ×3
constructor ×3
c++11 ×2
inheritance ×2
arrays ×1
copy-elision ×1
deep-copy ×1
gcc ×1
stdstring ×1
templates ×1
typescript ×1