声明在实例化时不会有的引用成员变量
Declare reference member variable that you won't have at instantiation
来自 Java,C++ 正在打破我的大脑。
我需要一个 class 来保存对在主作用域中定义的变量的引用,因为我需要修改该变量,但我无法实例化该 class 直到一些内部循环,在那之前我也没有参考。这对我的 Java 大脑造成了无穷无尽的挑战:
我习惯于声明一个变量来确定它的作用域,在知道将进入该变量的实际值之前。例如,创建一个变量,它将在我的主范围内保存一个对象,如 MyClass test;
,但 C++ 不能忍受真空,将使用默认构造函数在当时和那里实际实例化它。
此外,鉴于我想稍后将引用传递给该对象 (class),如果我希望将引用作为成员变量保存,似乎成员变量必须在声明时初始化。我不能只在我的 class 定义中声明成员变量,然后在我的程序流程中使用一些 MyClass::init(int &myreference){}
来分配引用。
所以这使得我想做的事情看起来不可能 - 在 class 的实例化之外的任何其他时间传递对要作为成员变量保存在 class 中的变量的引用。 [更新,在 stack-overflow-rubber-ducking
中,我意识到在这种情况下我实际上可以提前知道这些变量,因此可以避免所有这些混乱。但我认为这个问题仍然是相关的,因为我确定我会 运行 经常进入这种模式]
我只能用指针吗?是否有一些明显的技术是我的 Google-fu 时间无法发掘的?
TLDR; - 当您无法在实例化/构造函数(即:列表初始化)中定义成员变量时,如何正确使用 class 成员变量中的引用?
Declare reference member variable that you won't have at instantiation
必须初始化所有引用。如果你没有任何东西来初始化它,那么你就没有参考。
您似乎要查找的类型是指针。与引用一样,指针是一种间接形式,但与引用不同的是,指针可以默认初始化,并且它们具有空状态,并且可以在初始化后指向一个对象。
重要说明:与 Java 引用不同,C++ 引用和指针通常不会延长它们引用的对象的生命周期。很容易在不知不觉中继续引用一个超出其生命周期的对象,并且尝试通过此类无效引用进行访问将导致未定义的行为。因此,如果您确实在成员中存储了一个对象的引用或指针(作为参数提供),那么您应该向提供该对象的调用者明确说明,以便他们可以确保正确的生命周期.例如,您可以将 class 命名为 reference_wrapper
(顺便说一句,它是标准库中存在的 class)。
为了具有类似于 Java 引用的语义,您需要共享所有权,这样每个所有者都可以延长引用对象的生命周期。在 C++ 中,这可以通过共享指针 (std::shared_ptr
) 来实现。
但是请注意,通常最好不要在 Java 中思考,并将您的 Java 思想转化为 C++,但最好还是学会在 C++ 中思考。共享所有权很方便,但它有成本,你必须考虑你是否负担得起。 Java 程序员必须“忘掉”Java 才能写出好的 C++。您还可以用大多数其他编程语言替代 C++ 和 Java,同样适用。
it seems that the member variable must be initialized when it's declared.
成员变量在声明时不直接初始化。如果您在成员声明中提供了一个初始化程序,那么这是一个默认的成员初始化程序,如果您没有在构造函数的成员初始化程序列表中为该成员提供一个初始化程序,将使用它。
您可以初始化成员引用以引用在(a 的成员初始化列表)构造函数中作为参数提供的对象,但实际上不能在初始化 class 实例之后。
引用成员变量的问题甚至比引用和指针所具有的生命周期挑战还要多。由于引用不能指向其他对象,也不能默认初始化,这样的成员必然会使 class 成为非“常规”,即 class 不会像基本类型那样表现得相似。这使得此类 classes 使用起来不太直观。
长话短说:
- Java 习语在 C++ 中不起作用。
- Java 引用与 C++ 引用有很大不同。
- 如果您认为您需要参考成员,请退后一步并考虑其他想法。首先要考虑的是:不是引用存储在别处的对象,而是可以将对象存储在 class 中吗?首先需要 class 吗?
来自 Java,C++ 正在打破我的大脑。
我需要一个 class 来保存对在主作用域中定义的变量的引用,因为我需要修改该变量,但我无法实例化该 class 直到一些内部循环,在那之前我也没有参考。这对我的 Java 大脑造成了无穷无尽的挑战:
我习惯于声明一个变量来确定它的作用域,在知道将进入该变量的实际值之前。例如,创建一个变量,它将在我的主范围内保存一个对象,如
MyClass test;
,但 C++ 不能忍受真空,将使用默认构造函数在当时和那里实际实例化它。此外,鉴于我想稍后将引用传递给该对象 (class),如果我希望将引用作为成员变量保存,似乎成员变量必须在声明时初始化。我不能只在我的 class 定义中声明成员变量,然后在我的程序流程中使用一些
MyClass::init(int &myreference){}
来分配引用。
所以这使得我想做的事情看起来不可能 - 在 class 的实例化之外的任何其他时间传递对要作为成员变量保存在 class 中的变量的引用。 [更新,在 stack-overflow-rubber-ducking
中,我意识到在这种情况下我实际上可以提前知道这些变量,因此可以避免所有这些混乱。但我认为这个问题仍然是相关的,因为我确定我会 运行 经常进入这种模式]
我只能用指针吗?是否有一些明显的技术是我的 Google-fu 时间无法发掘的?
TLDR; - 当您无法在实例化/构造函数(即:列表初始化)中定义成员变量时,如何正确使用 class 成员变量中的引用?
Declare reference member variable that you won't have at instantiation
必须初始化所有引用。如果你没有任何东西来初始化它,那么你就没有参考。
您似乎要查找的类型是指针。与引用一样,指针是一种间接形式,但与引用不同的是,指针可以默认初始化,并且它们具有空状态,并且可以在初始化后指向一个对象。
重要说明:与 Java 引用不同,C++ 引用和指针通常不会延长它们引用的对象的生命周期。很容易在不知不觉中继续引用一个超出其生命周期的对象,并且尝试通过此类无效引用进行访问将导致未定义的行为。因此,如果您确实在成员中存储了一个对象的引用或指针(作为参数提供),那么您应该向提供该对象的调用者明确说明,以便他们可以确保正确的生命周期.例如,您可以将 class 命名为 reference_wrapper
(顺便说一句,它是标准库中存在的 class)。
为了具有类似于 Java 引用的语义,您需要共享所有权,这样每个所有者都可以延长引用对象的生命周期。在 C++ 中,这可以通过共享指针 (std::shared_ptr
) 来实现。
但是请注意,通常最好不要在 Java 中思考,并将您的 Java 思想转化为 C++,但最好还是学会在 C++ 中思考。共享所有权很方便,但它有成本,你必须考虑你是否负担得起。 Java 程序员必须“忘掉”Java 才能写出好的 C++。您还可以用大多数其他编程语言替代 C++ 和 Java,同样适用。
it seems that the member variable must be initialized when it's declared.
成员变量在声明时不直接初始化。如果您在成员声明中提供了一个初始化程序,那么这是一个默认的成员初始化程序,如果您没有在构造函数的成员初始化程序列表中为该成员提供一个初始化程序,将使用它。
您可以初始化成员引用以引用在(a 的成员初始化列表)构造函数中作为参数提供的对象,但实际上不能在初始化 class 实例之后。
引用成员变量的问题甚至比引用和指针所具有的生命周期挑战还要多。由于引用不能指向其他对象,也不能默认初始化,这样的成员必然会使 class 成为非“常规”,即 class 不会像基本类型那样表现得相似。这使得此类 classes 使用起来不太直观。
长话短说:
- Java 习语在 C++ 中不起作用。
- Java 引用与 C++ 引用有很大不同。
- 如果您认为您需要参考成员,请退后一步并考虑其他想法。首先要考虑的是:不是引用存储在别处的对象,而是可以将对象存储在 class 中吗?首先需要 class 吗?