3

次のコードセーフです(DEBUGで動作します):

void takesPointer(const Type* v);//this function does read from v, it doesn't alter v in any way
Type getValue();
...
takesPointer(&getValue());//gives warning while compiling "not an lvalue"
...
Type tmp = getValue();
takesPointer(&tmp);//this is safe, and maybe I should just do it, instead of posting here

それで - それは安全ですか?それを忘れて、明示的な tmp でコードを使用する必要がありますか?

とにかく-オプティマイザーがこの呼び出しから戻る前に一時的なものを強制終了できるかどうか、私はまだ興味があります:

takePointer(&getValue())

編集:ありがとうございました!残念ながら、関数「takesPointer」(ライブラリの一部です)を変更することはできません。関数「takesReference」でラップすることしかできませんでした。これはtakePointerを呼び出します-これによりコピーが削除されるか、コンパイラは引き続き作成できますかコピー(「タイプ」はint-3x3-Matrixなので、それほど悪くはありませんが、それでも...)?

inline void takesReference(const Type& v){ takesPointer(&v); }

破壊の時期について:「takesPointer」が戻った後、または呼び出された後に破壊されますか?

4

5 に答える 5

10

他の回答が述べているように、一時的なアドレスを取ることはできません。ただし、署名を変更すると、

void takesPointer(const Type* v);

void takesPointer(const Type& v);

次に、次のコードは警告なしでコンパイルされます。

takesPointer(getValue());

一時的なものを const 参照にバインドすることが許可されており、まったく同じように機能するはずだからです。

于 2010-02-25T14:28:04.533 に答える
7

標準はあなたがすることを禁じています&getValue()-それは左辺値ではないからです。通常、これ許可されている場合、その関数呼び出しからの一時的な結果は、外部関数が戻り、式全体の他のすべての処理が完了するまで存続します。これは「完全な式の終了後に一時的なものを破棄する」と呼ぶことができ、次のようなことが期待どおりに機能することを保証します。

// the temporary string is alive until the whole expression has been processed
cout << string("hello");

コンパイラは診断を行います。これが、不正なコードに対して標準が必要とするすべてです。たとえば、コンパイラにコンパイルの中止を強制することはありません。しかし、不正なコードが診断された後、コンパイラは必要なことをすべて行うことができます。そのため、自分の場合にコンパイラが何をするかを知りたい場合は、そのマニュアルを読む必要があります。

于 2010-02-25T14:03:32.233 に答える
1

これにより、コピー*とコンパイルが防止されます。

const Type& tmp = getValue(); 
takesPointer(&tmp);

コンパイラが多くの場合、これを行うため、コピーの防止は少し強力です。コピー コンストラクターにアクセスする必要がありますが、コンパイラーはそれを使用しないことがよくあります。

#include "iostream"
class Type
{
public:
    explicit Type(int val) : m_val(val) { std::cout << "ctor";};
    Type(const Type& copy)
    {
        std::cout << "copy";
    };
private:
    int m_val;
};

Type getValue() { Type r(0); return r;};
void takesPointer(const Type* const)
{

};

int main(int argc, char* argv[])
{
    const Type tmp = getValue(); 
    takesPointer(&tmp);
}

リリースでは「ctor」のみ、デバッグでは「ctorcopy」のみを出力します。(MVS2005)

于 2010-02-25T14:13:32.253 に答える
0

Yes, it is safe, albeit illegal in the current form. You can work around the error by using an explicit intermediate cast to const-reference type

takesPointer( &(const Type &) getValue() );

This makes it perfectly legal as long as the temporary object is alive, which is till the end of evaluation of the full expression.

Moreover, you can even cast away the constness and modify the temporary object through the pointer (keeping in mind that it will be destroyed at the end of full expression). This is perfectly legal as long as the temporary object itself is not constant.

Using a comma operator, you can "stretch" full expressions, and thus write quite extensive sequences of operations that work with a "long-lived" temporary object

Type *p;
p = &(Type &) (const Type &) getValue(), modify(p), print(p), modifyAgain(p), print(p);
// Not using C++ casts for brevity

The practice is rather questionable though and most of the time there's no point in doing this.

于 2010-02-25T15:02:07.430 に答える
0

非 const 右辺値を const 参照左辺値にバインドすることは許可されていますが、それを const ポインター左辺値にバインドしています。

いいえ、オプティマイザーは をgetValue()呼び出す前にの結果を破壊することはできませんtakePointer()

于 2010-02-25T14:01:45.370 に答える