【问题标题】:Initialize a pointer to primitive to a temporary object将指向原始对象的指针初始化为临时对象
【发布时间】:2013-02-12 01:36:52
【问题描述】:

我认为这是 MSVC 中的有效代码:

MyClass* pMc = &MyClass();

但是,当我尝试对原始数据类型执行相同操作时,我遇到了编译错误。

int* pInt = &int();

错误:

error C2101: '&' on constant

我有 3 个问题:

  1. 为什么int() 给我一个常数?
  2. 为什么错误C2101首先存在?获取常量的地址有什么问题?
  3. 有没有一种方法可以声明指向临时对象的 int(或其他原始)引用? (即不先创建局部变量)

关于第三个问题:

我确实不想做这样的事情:

int i = int();
int* pInt = &i;

如果我正在处理对本地对象的引用(原因无关紧要),我不希望每个对象都声明两次。这很乏味,很烦人,而且名字会很混乱。

【问题讨论】:

  • 您确实意识到int() 可能与0 相同?所以你的声明实际上等同于&0,这没有多大意义。
  • 另外&MyClass() 不是一个完全有效的代码,它不应该编译。 MSVC++ 愚蠢地允许它。
  • 标准不允许对临时对象的非常量引用,尽管 MSVC 有一个扩展来规避这一点。最好不要尝试将具有未定义行为的解决方案组合在一起。
  • @David 没有意识到它和 0 完全一样。为什么它不给我一个对象?。 Seth Carnegie Chris 解释了它编译的原因。谢谢大家。
  • completely valid code哦?

标签: c++ pointers constructor initialization constants


【解决方案1】:

我不知道1的答案(我认为错误是错误的,因为我很确定int()不是一个常数),但是

(2) 获取临时地址是非法的。您的代码不应该编译,但由于非标准的 MSVC++ 扩展,它可以编译。

(3) 是的,使用 rvalue-references 或 const lvalue-references:

const int& tmp = int();
int&& tmp = int(); // same as former but isn't const

临时对象的生命周期将延长,直到引用超出范围。

但是,我希望您有充分的理由使用上述两种方法之一,而不是

int tmp;

【讨论】:

  • 它是一个扩展的事实解释了一切。正如我在 cmets 中提到的,我没有任何理由,我在询问语言。非常感谢!
【解决方案2】:

代码行在一个编译器中以违反标准的方式编译,但在下一行取消引用该指针是未定义的行为。所以要小心。

我认为这可能有效:

template<typename T>
T* make_tmp_ptr(T&&t) {
   return &t;
}

然后调用make_tmp_ptr(int()),您将获得一个指向临时int 的指针,该指针将持续到表达式结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-14
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多