【问题标题】:What would be an use case for a function returning a const pointer (int * const, for example)?返回 const 指针(例如 int * const)的函数的用例是什么?
【发布时间】:2012-03-19 19:16:16
【问题描述】:

标题不言自明,但我还是举个例子吧。

int sum(int a, int b){
    return a + b;
}

我们可以改写成

int sum(const int a, const int b){
    return a + b;
}

但是返回一个 const int 呢?有什么用吗?

const int sum(const int a, const int b){
    return a + b;
}

调用者必须将 const 返回复制到一个 const 左值。这是不是太严格了?您知道这可能是一个很好的设计选择的任何用例吗?

好的,我对问题主体不是很清楚。考虑一个类似于汇编添加的 sum 函数:

int *sum(int *a, int b){
    *a += b;
    return a;
}

将 const 添加到参数中:

int *sum(int * const a, const int b){
    *a += b;
    return a;
}

也让返回 const 怎么样?这是有原因的吗?

【问题讨论】:

  • 限制太多。无论如何,当您按价值返回时,它有什么作用?为什么sum 函数在我调用它后告诉我如何处理我的变量?这没有任何意义。
  • 标题和正文提出了两个完全不同的问题。是哪一个?
  • 你需要区分const pointerpointer to a const
  • 您使用的是 C 还是 C++?这里的答案非常不同。

标签: c++ c constants


【解决方案1】:

我只能将其视为意向声明。

don't change this value 更多的东西 - if you get this value, you shouldn't need to change it

这实际上只完成了意图,因为您无论如何都可以更改值:http://ideone.com/Mf8Ge

【讨论】:

  • 我也正要这么说;没有什么可以阻止你添加它,或者像function_that_returns_const_int() + 543; 这样的东西。但请注意,您并没有真正改变它的价值,而是从 const 的价值创造了一个新价值。
【解决方案2】:

很多 的情况可能会返回一个 const 指针或一个 const 对象。我无法想象任何真实的情况,您希望将原始类型返回为const

我不确定你的问题是什么,在标题中你在谈论int* const,但在代码示例中你有一个const int

以下是constT* 的不同组合的一些示例(C++ 中)。

指向 const(原始类型)的指针

const int* someFuncion();

您有一个指向常量的指针,这意味着您可以更改指针但不能更改指向的对象/值。请注意someFunction() 不得返回指向堆栈分配变量的指针(const 或不)。我假设指针是有效的。例如:

const int* value = someFunction();

// Next line is valid, value will hold a new pointer
value = anotherFunction(); 

// Next line is not valid, pointed value cannot be changed
*value = 10;

指向 const(对象)的指针

const T* someFunction();

你有一个指向常量的指针。这意味着您可以更改指针以指向另一个对象,但不能更改指向的对象状态。这并不意味着您不能使用该对象,只是该对象是 const 然后您只能使用其标记为 const 的方法,读取其字段并写入其可变字段。一个常量方法定义为:

void method() const;

它可以有任何返回类型和任何参数,关键是它用const 修饰符标记。这意味着它不会改变对象状态(同样排除mutable对象)。

现在举个例子,T 声明为:

class T
{
public:
 void dump() const
 {
  // Dump the value to console, for example
 }

 void increaseValue()
 {
  ++m_value;
 }

private:
 int m_value;
};

想象一下编写以下代码:

const T* value = someMethod();

// Next line is valid, value will hold a new pointer
value = anotherMethod();

// Next line is not valid, we cannot change the object state
value->increaseValue();

// Next line is valid, we do not change the object state
value->dump();

常量指针(原始类型)

int* const someFunction();

您有一个常量指针,这意味着您可以更改指向的值,但不能将另一个内存位置分配给指针本身。例如:

int* const value = someFunction();

// Next line is not valid, value cannot be changed
value = anotherFunction();

// Next line is valid, you can change the variable pointed by value
*value = 10;

常量指针(对象)

T* const someFunction();

您有一个常量指针,这意味着您可以更改指向的对象状态,但不能将另一个内存位置分配给指针本身。例如:

T* const value = someFunction();

// Next line is not valid, value cannot be changed
value = anotherFunction();

// Next lines are both valid, we can do whatever we want with the object
value->increaseValue();
value->dump();

指向常量的常量指针

const int* const someFunction();

这是先前声明的混合。上述所有(限制性)规则均有效。这意味着您无法更改指针,也无法更改指向的值。

注意事项

const 修饰符不限于用于指针和函数返回值。例如:

// PI value cannot be changed
const int PI = 3.14f;

// I have a pointer to a constant value
const* int pPI = Π

// I have a constant pointer to a constant value, note that
const* int const pPI2 = Π

请记住,const 修饰符始终可以使用 C 样式转换或 const_cast 删除。

结论

那么,回到你的问题,返回值 const int 的函数有用吗?

如果它是一个指针,我的答案是 yes,即使它可以通过强制转换移除:const 的目的是 传达 意图(让您免于很难找到愚蠢的错误),因此您的功能可以进行更多的交流,并且可以更好地使用它。从您的上一个示例更新此内容,我的答案是,在适用的地方使用 const。谁会调用你的代码会感谢你(你会自己做)。

如果它只是一个const int(或其他原始类型),那么您可能很少需要编写类似的东西。很多时候它们只是长时间计算的中间结果,然后将它们声明为const 是没有用的(原始类型不会改变,但会组合起来创建一个新值)。但是请注意,如果将它们声明为const 有意义,那么您应该 这样做。我想更常见的是看到一个常量原始类型声明为局部变量(再次确保它不会被错误地更改)。例如:

// This local variable cannot be modified
const int rate = (calculateX() + calculateY()) / calculateRateFactor();

或者在函数中,为什么不呢?如果您始终使用此规则(const 如果不应该更改),那么您会在参数不是 const 时即时看到,那么您会明白您会在某处修改它(也许用小、隐藏、漂亮的 ++ 位于屏幕最右侧)。

// With this prototype I'm sure I won't change a or b by mistake inside
// the function body.
int someFunction(const int a, const int b);

对于对象,我认为使用 const 修饰符更为常见(因为 const T 返回类型通常很有意义),例如:

// This object cannot be changed, just moved all around
const order* getNextOrderToStore();

话题并没有结束,当然是因为别名、可变变量、运算符重载以及 C 和 C++ 之间的差异......

【讨论】:

    【解决方案3】:

    不,我看到很少有这样有用的情况,因为它实际上什么也没做,而且它限制了调用者可以对返回值做什么。

    【讨论】:

    • 调用者不能用返回值做什么?
    【解决方案4】:

    调用者必须将 const 返回复制到一个 const 左值。

    不,根本不会。事实上,它可能永远不会复制它。或者它可能会将其复制到一个可变的左值。

    const rvalues 没有意义,从来没有,也永远不会。

    【讨论】:

    • 好吧,有些人可能会说禁止分配给临时对象有用的,但实际上,这只是禁止 (N)RVO 和 C++11 甚至更多重要的是移动语义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多