天道酬勤,学无止境

如何在 c++ 中将`this`传递给没有循环引用(或丢失类型)的构造函数?(How can I pass `this` to a constructor without circular references (or losing type) in c++?)

问题

编辑:这已被标记为重复。 我相信Q:我可以用什么来解决我的问题,A:这个东西~和~ Q:这个东西是什么? - 答:大而深入的答案。 我不确定官方对此的裁决是什么。

我有两个课程都需要互相了解

// Creator.h
#pragma once
#include "Creation.h"
class Creator {
  Creator() {
    myThing = new Creation(*this);
  }
  int age = 42;
  Creation myThing*;
}

.

// Creation.h
#pragma once
#include "Creator.h"
class Creation {
  Creation(Creator &whoMadeMe) {
    std::cout << whoMadeMe.age;
  }
}

问题是,每当我做这样的事情时,我都会收到一个错误,即其中一个或另一个尚不存在。 在这种情况下, Creation(Creator &whoMadeMe)将给出错误Creator does not exist ,因为 Creation 类尚未准备好引用。

到目前为止,我总是找到一种方法让一个类知道另一个类,或者可能使用一些父类来避免引用引用回来的类。 但是我在这里陷入了僵局,我需要这两个类来了解彼此及其属性,并且我需要一个来创建另一个。

因此,在这样的场景中,必须将this指针传递给构造函数,如何在不创建循环引用或不得不丢失/重新输入类型的情况下做到这一点?

此外,如果丢失/重铸打字是最好的解决方案,请告诉我。 我一直被告知要避免它,因此我假设它不是解决方案。

回答1

您需要将声明(在 .h 文件中)和实现(在 .cpp 文件中)分开。 然后在头文件中使用前向声明来防止循环引用。 在实现文件中,您可以使用包含。

它将解决您的问题,但也会优化您的编译。

检查什么是 C++ 中的前向声明? 以及将类代码分离为头文件和 cpp 文件。

只要您不使用类,而仅将属性或参数声明为指向该类的指针或引用,您就可以使用class Creator; 而不是#include "Creator.h"

回答2

不确定这是最佳实践,但您可以使用template来解决这个问题

#include <iostream>

class Creation 
{
public:
    template<typename Creator> // type concept of Creater
    Creation(Creator &whoMadeMe) 
    {
        std::cout << whoMadeMe.age;
    }
};

class Creator 
{
public:
    Creator()
    {
        myThing = new Creation(*this);
    }
    int age = 42;
    Creation * myThing = nullptr;
};

神螺栓链接:https://godbolt.org/z/ILbFpS

顺便说一句,小心使用new 。 或者使用智能指针让生活更轻松。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在 C++ 中将数组作为参数传递(Passing an array as an argument in C++)
    问题 我正在编写一个合并排序函数,现在我只是在使用一个测试用例数组(没有输入 - 目前这是静态的)。 我不知道如何将数组作为参数传递。 这是我现在的代码: //merge sort first attempt #include <iostream> #include <algorithm> #include <vector> int mergeSort(int[]); int main() { int originalarray[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 }; mergeSort(originalarray[]); } int mergeSort(int[] originalarray) { int num = (sizeof(originalarray) / sizeof(int)); std::vector < int > original(num); if (num > 2) { return num; } // Fill the array using the elements of originalarray // This is just for demonstration, normally original will be a parameter, // so you won't be filling it up
  • 创建一个新对象并传入方法参数 [关闭](Creating a new object and passing in method parameter [closed])
    问题 关闭。 这个问题需要细节或清晰度。 它目前不接受答案。 想改善这个问题吗? 通过编辑此帖子添加详细信息并澄清问题。 5年前关闭。 改进这个问题 在 Java 中,我们可以创建一个新对象并将其传递给其参数中的方法,如下所示: wrapper.set_state( new Medium() ); 在 C++ 中与 this 等价的是什么? 我想我可以先创建对象然后传递它,但是能够在参数中创建它看起来更整洁。 回答1 在 Java 中 wrapper.set_state( new Medium() ); 创建一个新的、引用计数的 Medium 实例,并通过引用传递给包装器的 set_state 函数。 在 C++ 中,上述代码在技术上是有效的,在您的包装类 set_state 中将定义为: void set_state(Medium* medium); 但是你要做的是将一个非引用计数的指针传递给一个新的 Medium 实例。 您将负责确保稍后将其delete 。 如果所有 set_state 所做的都是这样: void set_state(Medium* medium) { this->medium = medium; } 每次对 set_state 进行第二次调用时,都会引入内存泄漏。 在 C++ 中,当你像这样覆盖原始指针时,没有引用计数。 如果没有人再指向分配,分配就会丢失
  • C ++-传递对std :: shared_ptr或boost :: shared_ptr的引用(C++ - passing references to std::shared_ptr or boost::shared_ptr)
    问题 如果我有一个需要与shared_ptr一起使用的函数,将它的引用传递给它(不是避免复制shared_ptr对象)会更有效吗? 可能的不良副作用是什么? 我设想了两种可能的情况: 1)在函数内部复制参数,例如 ClassA::take_copy_of_sp(boost::shared_ptr<foo> &sp) { ... m_sp_member=sp; //This will copy the object, incrementing refcount ... } 2)在函数内部仅使用参数,例如 Class::only_work_with_sp(boost::shared_ptr<foo> &sp) //Again, no copy here { ... sp->do_something(); ... } 在这两种情况下,我都看不出有通过值而不是通过引用传递boost::shared_ptr<foo>的充分理由。 传递值只会由于复制而“临时”增加引用计数,然后在退出功能范围时将其递减。 我在俯视什么吗? 为了澄清,在阅读了几个答案之后:我完全同意过早优化的问题,并且我总是尝试先介绍热点,然后再进行热点工作。 如果您知道我的意思,我的问题更多是从纯粹的技术代码角度来看。 回答1 唯一的shared_ptr实例的目的是(尽可能)保证,只要此shared_ptr在范围内
  • 如何将 C# 对象引用传入和传出 C++(How to pass C# object references to and from C++)
    问题 有没有办法通过本机互操作将 C# 对象引用(类类型,而不是结构)传入和传出 C++? 这是我的用例: 我正在尝试用 C# 编写游戏引擎,但想使用本机 (C++) 物理库。 物理库维护它自己的所有物理身体的内部状态,并让用户将少量数据(一个指针)与每个身体相关联。 在物理模拟滴答之后,库提供所有移动的物理实体的列表。 我想遍历这个列表并将所有更改传递给相应的 C# 对象。 问题是:将 C# 中的对象与 C++ 中的相应物理体相关联的最佳方法是什么? 我可以想到几种方法: 给每个物理身体一个某种类型的 ID,在 C++ 中将 ID 与物理身体相关联,并在 C# 中维护一个 ID 到相应对象的映射。 即使使用优化的映射机制,这对我来说似乎也是不必要的间接。 利用将 C# 委托(可以隐式引用 C# 对象实例)编组为 C++ 函数指针的能力。 这可能是最好的方法; 我不知道 C# 如何实现委托以及这会带来什么类型的开销。 寻找其他方式在 C++ 中引用 C# 对象,并将该引用与每个原生物理体相关联。 有没有我不知道的选项 3 之类的机制? C++/CLI 不是一个选项,因为我想支持没有它的平台。 回答1 我建议使用专为这种情况设计的工具,即System.Runtime.InteropServices.GCHandle 。 用法 在:
  • C++如何将'this'传递给指针引用(C++ how to pass 'this' to pointer reference)
    问题 我有一个主类,我喜欢将它的指针引用传递给我创建的对象,但它给了我错误: 错误 1 ​​错误 C2664:“GameController::GameController(GameLayer *&)”:无法将参数 1 从“GameLayer *const”转换为“GameLayer *&” 我在 GameLayer 中有什么(主要对象) m_pGameController = new GameController(this); 在 GameController 我有这个构造函数 GameController(GameLayer*& GameLayer) { setGameLayer(gameLayer); // to GameLayer memeber ) } 原因是我需要能够从 GameController(GUI 东西)修改 GameLayer 中的数据 回答1 首先, this的类型可以是GameLayer * const或const GameLayer * const取决于成员函数是否为const 。 但是,它是一个const指针。 话虽如此,对指针type *&ref意味着您将修改指针,即它指向的对象。 “因为,这个指针是一个常量指针,你不能在引用的上下文中将它分配给一个非常量指针(GameLayer * p)”。 在引用指针的情况下,您不能分配给将修改this值的引用
  • void* 如何作为通用引用类型工作?(How does void* work as a universal reference type?)
    问题 来自编程语言语用学,由 Scott 对于系统编程,或为了便于编写保存对其他对象的引用的通用容器(集合)对象(列表、堆栈、队列、集合等),几种语言提供了通用引用类型。 在 C 和 C++ 中,这种类型称为 void * 。 在 Clu 中,它被称为 any; 在 Modula-2 中,地址; 在 Modula-3 中,refany; 在 Java 中,对象; 在 C# 中,对象。 在 C 和 C++ 中, void *如何作为通用引用类型工作? void *始终只是一个指针类型,而通用引用类型包含所有值,包括指针和非指针。 所以我看不出void *是一种通用引用类型。 谢谢。 回答1 void*指针通常会保存任何不是 C++ 成员指针的指针。 这在实践中相当不方便,因为您需要先将其转换为另一种指针类型,然后才能使用它。 您还需要将其转换为同一指针类型,它是从转变,使void* ,否则,你的风险不确定的行为。 qsort 函数就是一个很好的例子。 它接受一个void*指针作为参数,这意味着它可以指向任何数组。 您传递给qsort的比较函数必须知道如何将两个void*指针转换回数组元素的类型,以便对它们进行比较。 回答2 您困惑的症结在于,无论是void *的实例还是 Modula-3 的refany的实例,以及任何其他语言的“可以指代任何东西”类型的实例,都不包含它所指的对象。
  • 在 C++ 中将数组作为函数参数传递 [重复](Passing array as function parameter in C++ [duplicate])
    问题 这个问题在这里已经有了答案: 当函数具有特定大小的数组参数时,为什么要用指针替换它? (3 个回答) 5年前关闭。 我知道可以通过多种方式将数组传递给函数。 #include <iostream> #include <utility> using namespace std; pair<int, int> problem1(int a[]); int main() { int a[] = { 10, 7, 3, 5, 8, 2, 9 }; pair<int, int> p = problem1(a); cout << "Max =" << p.first << endl; cout << "Min =" << p.second << endl; getchar(); return 0; } pair<int,int> problem1(int a[]) { int max = a[0], min = a[0], n = sizeof(a) / sizeof(int); for (int i = 1; i < n; i++) { if (a[i]>max) { max = a[i]; } if (a[i] < min) { min = a[i]; } } return make_pair(max,min); } 我上面的代码只传递第一个元素,而它应该传递一个数组(或从技术上讲
  • 与共享数据相比,消息传递的性能损失(performance penalty of message passing as opposed to shared data)
    问题 最近有很多关于不使用锁和使用像 Erlang 这样的消息传递方法的嗡嗡声。 或者在函数式编程与 C++/Java 中使用不可变的数据结构。 但我关心的是以下几点: AFAIK,Erlang 不保证消息传递。 消息可能会丢失。 如果您必须担心消息丢失,算法和代码不会膨胀并再次变得复杂吗? 无论您使用什么分布式算法,都不能依赖于保证的消息传递。 如果 Message 是一个复杂的对象怎么办? 与将消息保存在共享位置(例如两个进程都可以访问的数据库)相比,复制和发送消息是否存在巨大的性能损失? 你真的能完全取消共享状态吗? 我不这么认为。 例如,在数据库中,您必须访问和修改相同的记录。 您不能在那里使用消息传递。 您需要锁定或采用乐观并发控制机制,然后对错误进行回滚。 Mnesia 是如何工作的? 此外,您并非总是需要担心并发性。 任何项目都会有一大段代码,它们根本不需要处理并发或事务(但它们确实有性能和速度方面的问题)。 很多这些算法都依赖于共享状态(这就是传递引用或指针如此有用的原因)。 鉴于这个事实,在 Erlang 等中编写程序是一种痛苦,因为您无法做任何这些事情。 可能是,它使程序健壮,但对于解决线性规划问题或计算凸包等问题,性能更为重要,并且在与并发/事务无关的情况下强制算法的不变性等是一个糟糕的决定. 不是吗? 回答1 这就是现实生活:无论语言/平台如何
  • 通过引用传递 C++(pass by reference c++)
    问题 我的 C++ 老师告诉我,仅当我不打算更改函数内数组的任何内容时,才应使用按引用调用。 我在我的程序中传递了一些非常大的向量。 所有向量都将在函数内部进行修改。 我的矩阵大小约为[256*256][256][50] ... 有什么特别的理由不在这里使用 call-by 引用吗? AFAIK 通过引用调用应该更快并且消耗更少的内存? 回答1 除了关于何时以及如何为非原始类型传递可能的 const 引用的所有常见讨论之外,数组在这里非常特殊。 由于与 C 的向后兼容性,并且由于您的特定问题:数组可能很大,数组在 C 或 C++ 中从未真正按值传递。 该数组将衰减为指向第一个元素的指针,因此当您编写时: void foo( type array[100] ); 编译器实际上正在处理: void foo( type *array ); 不管数组的大小是多少(这里有两个常见的陷阱:相信该array是foo一个数组,并相信它可以保证有 100 个元素。 现在,在 C++ 中,您实际上可以通过引用传递数组,但引用必须是数组的具体类型,包括大小: void foo_array( type (&array)[100] ); 有趣的语法有告诉编译该函数将带类型的准确100元件的阵列type 。 这样做的好处是编译器可以为您执行大小检查: // assuming 'type' is defined
  • 现代 C++ 编译器的有效优化策略(Effective optimization strategies on modern C++ compilers)
    问题 我正在研究对性能非常关键的科学代码。 代码的初始版本已经过编写和测试,现在有了分析器,就可以从热点开始剃须周期了。 众所周知,一些优化,例如循环展开,如今由编译器比由程序员手动干预更有效地处理。 哪些技术仍然值得? 显然,我将通过分析器运行我尝试过的所有内容,但是如果有关于什么可行,什么不可行的传统智慧,它将为我节省大量时间。 我知道优化非常依赖于编译器和架构。 我正在使用面向 Core 2 Duo 的英特尔 C++ 编译器,但我也对什么适用于 gcc 或“任何现代编译器”感兴趣。 以下是我正在考虑的一些具体想法: 用手卷替换 STL 容器/算法有什么好处吗? 特别是,我的程序包含一个非常大的优先级队列(当前是std::priority_queue ),其操作需要花费大量总时间。 这是值得研究的东西,还是 STL 实现可能是最快的? 沿着类似的思路,对于需要大小未知但上限相当小的std::vector ,用静态分配的数组替换它们是否有利可图? 我发现动态内存分配通常是一个严重的瓶颈,消除它会导致显着的加速。 因此,我对通过值返回大型临时数据结构与通过指针返回与通过引用传递结果的性能权衡很感兴趣。 有没有办法可靠地确定编译器是否将 RVO 用于给定的方法(当然,假设调用者不需要修改结果)? 编译器的缓存感知能力如何? 例如,是否值得研究重新排序嵌套循环? 鉴于程序的科学性
  • 在构造函数中将指针/引用传递给现有对象的首选方法是什么?(What is preferred way of passing pointer/reference to existing object in a constructor?)
    问题 我将从例子开始。 boost中有一个很好的“标记器”类。 它需要一个字符串作为构造函数中的参数进行标记: std::string string_to_tokenize("a bb ccc ddd 0"); boost::tokenizer<boost::char_separator<char> > my_tok(string_to_tokenize); /* do something with my_tok */ 该字符串未在标记器中修改,因此它由 const 对象引用传递。 因此我可以在那里传递一个临时对象: boost::tokenizer<boost::char_separator<char> > my_tok(std::string("a bb ccc ddd 0")); /* do something with my_tok */ 一切看起来都很好,但是如果我尝试使用标记器,就会发生灾难。 经过简短的调查,我意识到,tokenizer 类存储了我给它的引用,并在进一步使用中使用。 当然,它不能很好地引用临时对象。 文档没有明确说明在构造函数中传递的对象将在以后使用,但好吧,也没有说明,它不会:) 所以我不能假设这一点,我的错误。 然而,这有点令人困惑。 在一般情况下,当一个对象通过常量引用获取另一个对象时,表明可以在那里给出临时对象。 你怎么认为?
  • 最喜欢的(聪明的)防御性编程最佳实践 [关闭](Favorite (Clever) Defensive Programming Best Practices [closed])
    问题 就目前而言,这个问题不适合我们的问答形式。 我们希望答案得到事实、参考或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。 如果您认为此问题可以改进并可能重新打开,请访问帮助中心以获取指导。 8 年前关闭。 如果你必须选择你最喜欢的(聪明的)防御性编码技术,它们会是什么? 虽然我目前的语言是 Java 和 Objective-C(有 C++ 背景),但可以随意用任何语言回答。 这里的重点是巧妙的防御技术,而不是我们这里 70% 以上的人已经知道的技术。 所以现在是时候深入挖掘你的技巧了。 换句话说,除了这个无趣的例子之外,试着想一想: if(5 == x)而不是if(x == 5) :避免意外赋值 以下是一些有趣的最佳防御性编程实践的示例(特定于语言的示例在 Java 中): - 锁定您的变量,直到您知道需要更改它们 也就是说,您可以将所有变量声明为final直到您知道需要更改它为止,此时您可以删除final 。 一个普遍不为人知的事实是,这对方法参数也有效: public void foo(final int arg) { /* Stuff Here */ } - 当坏事发生时,留下证据的踪迹 当您遇到异常时,您可以做很多事情:很明显,记录它并执行一些清理工作就很少了。 但是您也可以留下证据的痕迹(例如,将变量设置为“无法加载文件”或 99999
  • 将C ++对象传递到其自己的构造函数中合法吗?(Is passing a C++ object into its own constructor legal?)
    问题 我很惊讶地偶然发现以下作品: #include <iostream> int main(int argc, char** argv) { struct Foo { Foo(Foo& bar) { std::cout << &bar << std::endl; } }; Foo foo(foo); // I can't believe this works... std::cout << &foo << std::endl; // but it does... } 我正在将构造对象的地址传递给它自己的构造函数。 这看起来像是源代码级别的循环定义。 这些标准是否真的允许您在构造对象之前将对象传递给函数,或者这是未定义的行为? 考虑到所有类成员函数已经具有指向其类实例的数据的指针作为隐式参数,我认为这并不奇怪。 并且数据成员的布局在编译时是固定的。 注意,我不是在问这是有用还是个好主意。 我只是想学习更多有关课程的知识。 回答1 这不是未定义的行为。 尽管foo未初始化,但是您使用的是标准允许的方式。 在为对象分配空间之后,但在对其完全初始化之前,允许您以有限的方式使用它。 允许绑定对该变量的引用并获取其地址。 缺陷报告363:自类的初始化对此进行了说明: 如果是这样,UDT的自我初始化的语义是什么? 例如 #include <stdio.h> struct A { A() {
  • 如何传递对字符串的引用?(How to pass a reference to a string?)
    问题 我读到的关于scanf 、 gets和fgets内容都是有问题的; 要么是空白,要么是溢出,要么是复杂。 我正在学习 C 课程,因为我有足够的 Java 和其他语言编程经验,所以我决定创建自己的函数来使用getchar()函数从用户那里获取字符串输入。 我的代码的相关部分如下: bool get_string (char prompt[], char* string) { printf(prompt); // Prompt the user // Ensure string is allocated to store the null character and reset it if it has been initialized do { string = (char*)malloc(sizeof(char)); } while (string == NULL); int index = 0; char place = getchar(); while (place != '\n') // Obtain all characters before endl { string = (char*)realloc(string, sizeof(string) + sizeof(char)); // Create room in the array if (string ==
  • 如何实现数组 - llvm(How to implement arrays - llvm)
    问题 我正在研究使用 llvm c++ api 编写的玩具语言,我正在尝试实现数组。 我尝试了几种不同的方法,但没有一种效果很好。 这是我的目的: 可以类似于数组的类型(结构体、向量或数组都可以) 可以传递给函数和从函数返回可以有无限嵌套的数组(例如[8 x [8 x [8 x [...] ) 可以重新分配数组都是相同的类型数组是在创建时指定的有限长度。 理想情况下,它们类似于 swift 中的数组。 当前解决方案 目前我使用的是基本数组类型。 这将检查所有框,除了虽然可以将一维数组传递给函数并从函数返回,但多维(嵌套)数组必须通过指针传递。 这意味着我不仅必须将返回的指针位转换为正确的类型,而且还必须循环遍历每个元素并将其存储在适当的位置。 很快,这不仅变得非常混乱,而且速度也很慢。 向量 据我所知,您不能有嵌套向量。 例如。 这不起作用: <8 x <8 x i32>> 使用 malloc 最后,我尝试使用 malloc 分配适当的空间,然后对所有内容使用指针。 这与我目前的解决方案有许多相同的问题。 像 C++ 之类的东西? 以下面的例子为例: %1 = alloca [5 x i32], align 16 %2 = alloca i32*, align 8 %3 = getelementptr inbounds [5 x i32], [5 x i32]* %1, i32 0
  • 如何获取数组的大小? [复制](How to get the size of an Array? [duplicate])
    问题 这个问题在这里已经有了答案: 如何在 C++ 中使用数组? (5 个回答) 7年前关闭。 在 C# 中,我使用嵌入到我想要获取大小的数组的 Length 属性。 如何在 C++ 中做到这一点? 回答1 这真的取决于你所说的“数组”是什么意思。 C++ 中的数组的大小(即现在的“原始”字节大小)等于一项大小的 N 倍。 通过这种方式,可以使用sizeof运算符轻松获取项目数。 但这要求您仍然可以访问该数组的类型。 一旦你把它传递给函数,它就会被转换成指针,然后你就迷失了。 无法再确定大小。 您将不得不构建一些依赖于元素值来计算大小的其他方式。 这里有些例子: int a[5]; size_t size = (sizeof a / sizeof a[0]); // size == 5 int *pa = a; 如果我们现在丢失了名称“a”(以及它的类型),例如通过将“pa”传递给一个函数,而该函数只有那个指针的值,那么我们就不走运了。 然后我们就不能再收到尺寸了。 我们需要将大小与指向该函数的指针一起传递。 当我们使用new获取数组时,同样的限制适用。 它返回一个指向该数组元素的指针,因此大小将丢失。 int *p = new int[5]; // can't get the size of the array p points to. delete[] p
  • 在 C# 上使用 C++/CLI 的情况或优缺点是什么?(What are the situations or pros and cons to use of C++/CLI over C#)
    问题 我一直在关注 .NET CLR 有一段时间了,我选择的语言是 C#。 直到最近,我才意识到 C++/CLI 可以生成能够运行本机和托管代码的“混合模式”可执行文件。 现在知道了这一点,我的另一个开发者朋友正在讨论这个属性并试图确定这个能力何时以及如何有用。 我认为本机代码具有比托管代码更高效、更强大的能力,但代价是额外的开发时间。 过去,我严格使用原生 C++ 代码库,并使用 Interop 来利用我写入原生库的功能。 我可以看到不需要额外库的好处,但我很好奇使用 C++/CLI 而不是在 C# 中创建的单独托管可执行文件的所有优点/缺点,或者使用互操作调用纯本地 C++ 的可执行文件图书馆? (旁注:术语 Interop/PInvoke 是否可以互换,因为我不明白这些术语之间的区别,只是看到它们以相同的方式使用。) 回答1 使用 C++/CLI,广义上讲,您可以创建三种类型的对象: 托管类型。 这些将编译为与等效的 C# 基本相同的 IL。 这里没有表演机会。 原生类型。 编译为本机代码,就像您使用直接 C++ 一样。 混合模式类型。 这些编译为托管代码,但也允许您引用本机类型。 您可能认为 (3) 就像使用 PInvoke 代码编写 C# 代码来访问本机内容一样 - 除了所有 PInvoke 内容都是为您生成的。 当然,除此之外,还有一些注意事项—
  • c++核心指南--Philosophy
    本节的规则非常笼统。 理念规则摘要: P.1: 直接用代码表达思想P.2: 用ISO标准c++编写代码P.3: 明示意图P.4:理想情况下,程序应该是静态类型安全的P.5: 优先使用编译时检查而不是运行时检查P.6: 不能在编译时检查的内容应该可以在运行时进行检查P.7: 尽早捕获运行时错误P.8: 不要泄露任何资源P.9: 不要浪费时间和空间P.10: 优先使用不可变数据而不是可变数据P.11:封装凌乱的结构,而不是任其在代码中传播P.12:适当使用支持工具P.13: 适当使用支持库 理念化规则是笼统的、不能机械的检验的。.然而,反映这些理念主题的单个规则是可以机械的检验的。没有理念基础,更具体/特殊/可检验的规则缺乏合理性。 P.1: 直接用代码表达思想 原因 编译器不读注释(或设计文档),许多程序员也不读注释(或设计文档)。用代码表示的内容已经定义了语义,可以(原则上)由编译器和其他工具检查。 例子 class Date { public: Month month() const; // do int month(); // don't // ... }; month声明的第一个版本明确返回 Month同时也明确表达不会改变 Date 对象的状态。 第二个版本则让读者猜测,也为未捕捉的bug打开了更多的可能性。 坏的例子 里面的for循环是std::find的受限形式
  • Java基础知识点总结归纳整理成题库
    看了网上很多关于Java基础知识点总结归纳整理成题库的文章,但是感觉都不是很好,要么不全面,要么不准确,要么排版太乱了,所以今天整理了一份Java基础知识点总结归纳整理成题库,希望对大家有帮助哈~ 由于本文篇幅过长,博主为了方便大家阅读和收藏,特意将本文转成了一份PDF版的文档。 需要PDF版的朋友可以关注微信公众号:Java团长,发送“ 基础知识 ”即可获取哈~ 一、Java概述 1、何为编程 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。 为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。 2、什么是Java Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。 3、jdk1.5之后的三大版本 Java SE(J2SE,Java 2 Platform Standard Edition,标准版)Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器
  • 如何将局部引用变量传递给 lambda 函数,但该函数将在其关闭已完成时被调用?(How to pass a local referenced variable to a lambda function, but the function will be called when its closure is already finished?)
    问题 下面的代码应该打印两个相同的整数,但事实并非如此。 JavaScript 中的类似程序将打印两个相同的数字。 这似乎在C ++合理的,因为当stdfun执行, regfun已经完成,该local_var没有了当时存在的。 所以我的问题是我们如何才能像 JavaScript 默认那样正确访问超出其上下文生命周期的捕获的局部变量? #include <functional> #include <future> #include <cmath> #include <iostream> #include <ctime> #include <windows.h> using namespace std; int start_stdfun_in_a_new_thread(std::function<void()> stdfun) { int id = rand(); std::function<void()> call = [=]() { Sleep(1000);//let regfun finish stdfun(); }; std::async(std::launch::async,call); return id; } void regfun() { int local_var = -1; std::function<void()> stdfun = [=,&local_var](