【问题标题】:Explicit Assignment vs Implicit Assignment显式赋值与隐式赋值
【发布时间】:2011-07-19 18:03:36
【问题描述】:

我正在阅读 C++ 教程,但它实际上并没有给我带来两者之间的区别(除了语法)。这是教程中的引述。

您还可以在声明时为变量赋值。什么时候我们 使用赋值运算符为变量赋值(等于 符号),它被称为显式赋值:

int nValue = 5; // explicit assignment

您还可以使用隐式赋值为变量赋值:

int nValue(5); // implicit assignment

尽管隐式赋值看起来很像函数调用,但 编译器跟踪哪些名称是变量,哪些是变量 函数,以便它们可以正确解析。

有区别吗?一个比另一个更受欢迎吗?

【问题讨论】:

  • 这不是声明,而是定义。放弃该教程和read a decent book。 Thinking in C++ 是免费的,可以从作者的页面获得。
  • @Cat Plus Plus:这是一个定义,但这并不意味着它不是一个声明。
  • @JamesMcNellis:它应该是一个教程,调用定义声明无助于摆脱两者之间的混淆。也许我今天只是脾气暴躁。 :P
  • @Cat Plus Plus:说某事不是它实际上的样子也无助于摆脱混乱。
  • 有问题的教程是这个:learncpp.com/cpp-tutorial/…

标签: c++ implicit explicit


【解决方案1】:

第一个优先用于基本类型,如int;第二个是具有构造函数的类型,因为它使构造函数调用显式。

例如,如果您定义了一个可以从单个 int 构造的 class Foo,那么

Foo x(5);

优于

Foo x = 5;

(当传递多个参数时,无论如何您都需要前一种语法,除非您使用Foo x = Foo(5, "hello");,这很丑陋并且看起来像正在调用operator=。)

【讨论】:

  • 值得一提的是,使用构造语法,您需要小心大多数令人头疼的解析。
  • 另请注意,Foo x = 5 仅在 Foo::Foo(int) 未标记为 explicit 时才有效。
  • ...(继续@Vitus 评论)和Foo 复制构造函数是可访问的。
【解决方案2】:

对于原始类型,两者是等价的,但对于用户定义的类类型,存在差异。在这两种情况下,执行的代码都是相同的(在执行基本优化之后),但是如果我们初始化的元素不是我们正在构造的类型,则对类型的要求会有所不同。

copy-initialization (T t = u;) 等效于从 T 类型的临时对象复制构造,该临时对象已从 u 隐式转换为 t。另一方面,直接初始化等价于直接调用相应的构造函数。

虽然在大多数情况下没有区别,但如果采用 u 的构造函数声明为 explicit 或者如果 copy-constructor 不可访问,则 copy-initialization 会失败:

struct A {
   explicit A( int ) {}
};
struct B {
   B( int ) {}
private:
   B( B const & );
};
int main() {
   A a(1);      // ok
   B b(1);      // ok
// A a2 = 1;    // error: cannot convert from int to A
// B b2 = 1;    // error: B( B const & ) is not accessible
}

对于某些历史背景,最初的原始类型必须使用 copy-initialization 进行初始化。当 *initializer-list*s 被添加到语言中以初始化类的成员属性时,决定原始类型应该使用与类相同的语法进行初始化,以保持初始化列表中的语法统一和简单。同时允许通过copy-initialization 来初始化类,使用户定义的类型更接近原始类型。两种初始化格式的区别自然而然:int a = 5.0; 被处理为从5.0int 的转换,然后从int 初始化a。用户定义类型也是如此:T u = v; 被处理为从 vT 的转换,然后从转换后的值复制 u 的构造。

【讨论】:

    【解决方案3】:

    当您声明一个变量并对其进行初始化时,它们在该上下文中的功能是相同的。我通常将两者称为:

    int nValue = 5; // assignment syntax
    

    int nValue(5); // construction syntax
    

    对于基本类型,我更喜欢赋值而不是构造,因为它更自然,尤其是对于那些使用其他语言编程的人。

    对于类类型,我更喜欢构造语法,因为它避免了构造函数的存在。

    【讨论】:

    • 标准(N3242)调用语法T x = acopy-initializationT x(a)direct-initialization。两者都是调用构造函数T::T(a)的有效方式。
    猜你喜欢
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 2023-01-26
    • 2017-02-17
    • 2018-06-16
    • 2021-08-13
    • 2021-11-08
    相关资源
    最近更新 更多